@yoltra/core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,7 +48,30 @@ export type EventKey<EM extends EventMapBase> = {
48
48
  [C in keyof EM & string]: [C, keyof EM[C] & string];
49
49
  }[keyof EM & string];
50
50
  /**
51
- * A single event object: `{ channel, type, payload, id }`.
51
+ * Opaque, optional envelope metadata carried alongside an {@link Event}.
52
+ *
53
+ * @remarks
54
+ * The store never reads, validates or acts on this — it only carries it end to end, so
55
+ * reducers, middleware, effects, event subscribers and instrumentation all observe the same
56
+ * value. It is deliberately untyped at this level: consumers namespace their own keys (for
57
+ * example a tracing integration keeping provenance under `meta.trace`) rather than
58
+ * extending core with domain concepts.
59
+ *
60
+ * It is **not** part of the deduplication fingerprint, which is computed from
61
+ * `(channel, type, payload)` only. Two events differing solely in `meta` still dedupe.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * await store.emit('orders', 'created', payload, {
66
+ * meta: { trace: { origin: 'checkout-service', hop: 1 } },
67
+ * });
68
+ * ```
69
+ *
70
+ * @public
71
+ */
72
+ export type EventMeta = Readonly<Record<string, unknown>>;
73
+ /**
74
+ * A single event object: `{ channel, type, payload, id }`, plus optional `meta`.
52
75
  *
53
76
  * @typeParam EM - Event map.
54
77
  * @typeParam C - Channel key.
@@ -56,14 +79,16 @@ export type EventKey<EM extends EventMapBase> = {
56
79
  * @typeParam P - Payload type (defaults to `EM[C][T]`).
57
80
  *
58
81
  * @remarks
59
- * - The `id` field is automatically added by the store to enable deduplication.
82
+ * - The `id` field is automatically added by the store to enable deduplication, unless the
83
+ * emitter supplies one via {@link EmitOptions.id}.
60
84
  * - Used for preventing duplicate event processing (e.g., React Strict Mode).
85
+ * - `meta` is present only when {@link EmitOptions.meta} was supplied. See {@link EventMeta}.
61
86
  *
62
87
  * @example
63
88
  * ```ts
64
89
  * type EM = { ui: { toggle: boolean } };
65
90
  * type Evt = Event<EM, 'ui', 'toggle'>;
66
- * // { channel: 'ui'; type: 'toggle'; payload: boolean; id: string }
91
+ * // { channel: 'ui'; type: 'toggle'; payload: boolean; id: string; meta?: EventMeta }
67
92
  * ```
68
93
  *
69
94
  * @public
@@ -74,6 +99,11 @@ export interface Event<EM extends EventMapBase = EventMapBase, C extends keyof E
74
99
  payload: P;
75
100
  /** Unique identifier for deduplication and devtools tracking (automatically added by store) */
76
101
  id: string;
102
+ /**
103
+ * Optional caller-supplied metadata, carried through the pipeline untouched.
104
+ * Absent entirely unless {@link EmitOptions.meta} was supplied. See {@link EventMeta}.
105
+ */
106
+ readonly meta?: EventMeta;
77
107
  }
78
108
  /**
79
109
  * Generic "old → new" wrapper for fine-grained change notifications.
@@ -129,6 +159,41 @@ export interface EmitOptions {
129
159
  * is 0, using a short default window.
130
160
  */
131
161
  dedupKey?: string;
162
+ /**
163
+ * Use this exact id for the event instead of generating one.
164
+ *
165
+ * @remarks
166
+ * Intended for **idempotent re-emission**: a caller replaying an event from elsewhere (a
167
+ * peer store, a durable log) can preserve the original id so the same logical event keeps
168
+ * one identity everywhere, which makes it traceable across systems and in DevTools.
169
+ *
170
+ * The store does **not** enforce uniqueness — supplying a duplicate id does not dedupe the
171
+ * event. Deduplication is a separate, opt-in concern; see {@link EmitOptions.dedupKey}.
172
+ */
173
+ id?: string;
174
+ /**
175
+ * Metadata to attach to this event, carried through the pipeline untouched and visible to
176
+ * reducers, middleware, effects, subscribers and instrumentation. See {@link EventMeta}.
177
+ *
178
+ * @remarks
179
+ * Omitting this leaves `event.meta` genuinely absent rather than `undefined`, so event
180
+ * objects are byte-identical to those produced before this option existed.
181
+ */
182
+ meta?: EventMeta;
183
+ /**
184
+ * Bypass deduplication for this emit entirely, even when the store was created with
185
+ * {@link StoreSpec.dedupWindowMs} greater than 0.
186
+ *
187
+ * @remarks
188
+ * Content-based dedup fingerprints `(channel, type, payload)`, so a store with a dedup
189
+ * window silently collapses genuinely distinct events that happen to share a payload —
190
+ * repeated ticks with an empty payload, or the same event legitimately arriving twice from
191
+ * two different sources. Set this when the caller already guarantees distinctness by other
192
+ * means and needs every emit to land.
193
+ *
194
+ * Takes precedence over both {@link EmitOptions.dedupKey} and the store-level window.
195
+ */
196
+ skipDedup?: boolean;
132
197
  }
133
198
  export type Emit<EM extends EventMapBase> = <C extends keyof EM & string, T extends keyof EM[C] & string>(channel: C, type: T, payload: EM[C][T], opts?: EmitOptions) => Promise<void>;
134
199
  /**
@@ -145,12 +210,16 @@ export type Unsubscribe = () => void;
145
210
  * @public
146
211
  */
147
212
  export interface InstrumentedEvent<EM extends EventMapBase = EventMapBase> {
148
- /** The processed event, including its generated `id`. */
213
+ /**
214
+ * The processed event, including its `id` and any {@link EventMeta} the emitter attached.
215
+ * `meta` is absent unless it was supplied.
216
+ */
149
217
  event: {
150
218
  id: string;
151
219
  channel: string;
152
220
  type: string;
153
221
  payload: unknown;
222
+ meta?: EventMeta;
154
223
  };
155
224
  /** `true` if the event passed middleware and ran reducers; `false` if vetoed. */
156
225
  committed: boolean;
@@ -295,6 +364,26 @@ export type StoreSpec<R extends string, S extends Record<R, any>, EM extends Eve
295
364
  * @default 0 (disabled)
296
365
  */
297
366
  dedupWindowMs?: number;
367
+ /**
368
+ * Generates the `id` for each emitted event. Defaults to `crypto.randomUUID()`.
369
+ *
370
+ * @remarks
371
+ * Two reasons to override it. First, portability: `crypto.randomUUID` requires a **secure
372
+ * context** in browsers and is absent on some runtimes (React Native / Hermes), where the
373
+ * default would throw on every emit. Second, determinism: injecting a counter makes event
374
+ * ids stable across runs, which is what allows byte-exact assertions in tests.
375
+ *
376
+ * The factory must return a string. Uniqueness is the caller's responsibility.
377
+ *
378
+ * @default () => crypto.randomUUID()
379
+ *
380
+ * @example
381
+ * ```ts
382
+ * let n = 0;
383
+ * const store = createStore({ name: 'Test', reducer, idFactory: () => `evt-${++n}` });
384
+ * ```
385
+ */
386
+ idFactory?: () => string;
298
387
  /**
299
388
  * DevTools configuration options.
300
389
  *
@@ -324,6 +413,25 @@ export type StoreSpec<R extends string, S extends Record<R, any>, EM extends Eve
324
413
  * @param event - The event whose effect failed.
325
414
  */
326
415
  onEffectError?: (error: unknown, event: EventUnion<EM>) => void;
416
+ /**
417
+ * Invoked when a reducer throws.
418
+ *
419
+ * @remarks
420
+ * A reducer is meant to be pure and total, so a throw is a bug in application code — and it
421
+ * used to be almost invisible. Keyed reducers ran through a bus that logged and moved on,
422
+ * letting the event commit and its effects run; pattern reducers threw straight out of the
423
+ * drain, aborting the commit and notifying nobody. Both paths now isolate the failing slice
424
+ * and report here.
425
+ *
426
+ * The failing slice keeps its previous state; every other slice still reduces, and the event
427
+ * still commits if anything else changed. `emit()` never rejects because of a reducer error,
428
+ * so this hook is how a caller observes one.
429
+ *
430
+ * @param error - The thrown value.
431
+ * @param event - The event being reduced when it threw.
432
+ * @param slice - Name of the slice whose reducer threw.
433
+ */
434
+ onReducerError?: (error: unknown, event: EventUnion<EM>, slice: string) => void;
327
435
  };
328
436
  /**
329
437
  * Public Store surface.
@@ -384,9 +492,9 @@ export interface StoreInstance<R extends string = string, S extends Record<R, an
384
492
  */
385
493
  registerEffect(spec: EffectSpec<DeepReadonly<S>, EM>): Unsubscribe;
386
494
  /**
387
- * Dynamically add middleware.
495
+ * Dynamically add middleware, in either the function or the spec form.
388
496
  */
389
- registerMiddleware(mw: MiddlewareFunction<DeepReadonly<S>, EM>): Unsubscribe;
497
+ registerMiddleware(mw: MiddlewareInput<DeepReadonly<S>, EM>): Unsubscribe;
390
498
  /**
391
499
  * Dynamically add/remove a namespaced reducer slice at runtime.
392
500
  */
@@ -466,7 +574,7 @@ export interface StoreInstance<R extends string = string, S extends Record<R, an
466
574
  */
467
575
  hotReplace(partial: {
468
576
  reducer?: Record<R, ReducerSpec<S[R], EM>>;
469
- middleware?: MiddlewareFunction<DeepReadonly<S>, EM>[];
577
+ middleware?: MiddlewareInput<DeepReadonly<S>, EM>[];
470
578
  effects?: Array<EffectSpec<DeepReadonly<S>, EM>>;
471
579
  preserveState?: boolean;
472
580
  }): void;
@@ -487,6 +595,7 @@ export interface StoreInstance<R extends string = string, S extends Record<R, an
487
595
  type: string;
488
596
  payload: any;
489
597
  id: string;
598
+ meta?: EventMeta;
490
599
  }>): void;
491
600
  /**
492
601
  * Returns a structured introspection snapshot for DevTools UIs.
@@ -569,15 +678,6 @@ export interface StoreInstance<R extends string = string, S extends Record<R, an
569
678
  * };
570
679
  * ```
571
680
  *
572
- * @example Using `events` (legacy)
573
- * ```ts
574
- * const counterSpec: ReducerSpec<{ value: number }, MyEM> = {
575
- * state: { value: 0 },
576
- * events: [['ui', 'increment'], ['ui', 'decrement']],
577
- * reducer(s, evt) { ... },
578
- * };
579
- * ```
580
- *
581
681
  * @public
582
682
  */
583
683
  export interface ReducerSpec<S = any, EM extends EventMapBase = EventMapBase> {
@@ -587,14 +687,8 @@ export interface ReducerSpec<S = any, EM extends EventMapBase = EventMapBase> {
587
687
  state: S;
588
688
  /**
589
689
  * Event targeting using the unified `When` matcher.
590
- * Preferred over `events` for new code.
591
690
  */
592
691
  when?: When<EM>;
593
- /**
594
- * List of EventKeys `[channel, type]` that this reducer responds to.
595
- * @deprecated Use `when: { keys: [...] }` instead for better type inference.
596
- */
597
- events?: ReadonlyArray<EventKey<EM>>;
598
692
  /**
599
693
  * Pure reducer function: `(state, event) => nextState`.
600
694
  */
@@ -651,14 +745,8 @@ export type ReducerFunction<S = any, EM extends EventMapBase = EventMapBase> = (
651
745
  export interface EffectSpec<S = any, EM extends EventMapBase = EventMapBase> {
652
746
  /**
653
747
  * Event targeting using the unified `When` matcher.
654
- * Preferred over `events` for new code.
655
748
  */
656
749
  when?: When<EM>;
657
- /**
658
- * List of EventKeys `[channel, type]` that this effect responds to.
659
- * @deprecated Use `when: { keys: [...] }` instead for better type inference.
660
- */
661
- events?: ReadonlyArray<EventKey<EM>>;
662
750
  /**
663
751
  * Async effect handler: `(event, getState, emit) => void | Promise<void>`.
664
752
  */
@@ -986,11 +1074,23 @@ export type Dotted<Slice> = (keyof Slice & string) | Path<Slice>;
986
1074
  /**
987
1075
  * Deep readonly type: recursively makes all properties readonly.
988
1076
  *
1077
+ * @remarks
1078
+ * The built-in object types are handled before the general mapped-object case, because
1079
+ * mapping over one destroys it. `{ readonly [K in keyof Map<K, V>]: ... }` produces an object
1080
+ * carrying the *names* of a Map's methods with their signatures rewritten, so reading a Map
1081
+ * out of state and calling `.get()` on it was a type error even though the value at runtime
1082
+ * is an ordinary Map. The same applied to `Set`, `Date`, `RegExp` and any function stored in
1083
+ * state.
1084
+ *
1085
+ * Collections become their `Readonly*` counterparts, which is the same treatment arrays
1086
+ * already had. Functions are returned untouched: a function's properties are not state, and
1087
+ * mapping over them makes it uncallable.
1088
+ *
989
1089
  * @typeParam T - Type to make readonly.
990
1090
  *
991
1091
  * @public
992
1092
  */
993
- export type DeepReadonly<T> = T extends (infer A)[] ? ReadonlyArray<DeepReadonly<A>> : T extends object ? {
1093
+ export type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T extends (infer A)[] ? ReadonlyArray<DeepReadonly<A>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends ReadonlySet<infer V> ? ReadonlySet<DeepReadonly<V>> : T extends Date | RegExp | Promise<unknown> | Error ? T : T extends object ? {
994
1094
  readonly [K in keyof T]: DeepReadonly<T[K]>;
995
1095
  } : T;
996
1096
  /**
@@ -44,4 +44,27 @@ import { DeepReadonly } from '../types';
44
44
  *
45
45
  * @public
46
46
  */
47
- export declare function freezeState<T>(obj: T, seen?: WeakSet<object>): DeepReadonly<T>;
47
+ export declare function freezeState<T>(obj: T, seen?: WeakSet<object>, alias?: AliasWatch): DeepReadonly<T>;
48
+ /**
49
+ * Watches the freeze walk for one specific reference.
50
+ *
51
+ * @remarks
52
+ * Exists to turn a dev-only heisenbug into a named warning. Because the freeze is deep and
53
+ * in place, anything a reducer stores **by reference** is frozen too — the event payload, a
54
+ * module-level default, a cached response. Mutating that object afterwards then throws, only in
55
+ * development, from a stack that has nothing to do with the store, and the same code works in
56
+ * production because the freeze is compiled out.
57
+ *
58
+ * Freezing it is not the mistake: an object reachable from state genuinely must not be mutated,
59
+ * or state changes behind the store's back. Keeping the reference is. The walk already visits
60
+ * every node, so recognising one of them costs an identity comparison and lets the store say so
61
+ * at the moment it happens.
62
+ *
63
+ * @public
64
+ */
65
+ export interface AliasWatch {
66
+ /** The reference to look for while freezing. */
67
+ readonly watch: object;
68
+ /** Called if `watch` is reachable from the value being frozen. */
69
+ readonly onFound: () => void;
70
+ }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @yoltra/core v0.2.0
2
+ * @yoltra/core v0.4.0
3
3
  * (c) 2026 Manu Ramirez <@pixerael>
4
4
  * License: MIT
5
5
  * Homepage: https://yoltra.dev
@@ -7,5 +7,5 @@
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree
9
9
  */
10
- "use strict";var k=Object.defineProperty;var R=(a,e,t)=>e in a?k(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var d=(a,e,t)=>R(a,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class M{constructor(){d(this,"handlers",new Map)}on(e,t,r){let n=this.handlers.get(e);n||(n=new Map,this.handlers.set(e,n));let s=n.get(t);return s||(s=new Set,n.set(t,s)),s.add(r),()=>this.off(e,t,r)}off(e,t,r){const n=this.handlers.get(e);if(!n)return;const s=n.get(t);s&&(s.delete(r),s.size===0&&n.delete(t),n.size===0&&this.handlers.delete(e))}emit(e,t,r){const n=this.handlers.get(e);if(!n)return;const s=n.get(t);if(!(!s||s.size===0))for(const c of[...s])try{c(r)}catch(i){console.error("EventBus handler error:",i)}}clear(){this.handlers.clear()}}class P{constructor(){d(this,"handlers",new Map);d(this,"patternHandlers",new Map)}on(e,t,r){const n=String(t);if(this.isPattern(n)){const s=n;this.patternHandlers.has(e)||this.patternHandlers.set(e,new Map);const c=this.patternHandlers.get(e);return c.has(s)||c.set(s,[]),c.get(s).push(r),()=>this.offPattern(e,s,r)}else{const s=this.normalizeTypeKey(n);this.handlers.has(e)||this.handlers.set(e,new Map);const c=this.handlers.get(e);return c.has(s)||c.set(s,[]),c.get(s).push(r),()=>this.offExactNormalized(e,s,r)}}off(e,t,r){const n=this.normalizeTypeKey(String(t));this.offExactNormalized(e,n,r)}offExactNormalized(e,t,r){const n=this.handlers.get(e);if(!n)return;const s=n.get(t);if(!s)return;const c=s.indexOf(r);c!==-1&&s.splice(c,1),s.length===0&&n.delete(t),n.size===0&&this.handlers.delete(e)}offPattern(e,t,r){const n=this.patternHandlers.get(e);if(!n)return;const s=n.get(t);if(!s)return;const c=s.indexOf(r);c!==-1&&s.splice(c,1),s.length===0&&n.delete(t),n.size===0&&this.patternHandlers.delete(e)}emit(e,t,r){const n=String(t),s=this.normalizeTypeKey(n),c=this.handlers.get(e)?.get(s)??[],i=this.patternHandlers.get(e),o=[];if(i&&i.size){const l=this.normalizeTypeKey(n);for(const[u,p]of i.entries())this.matchPattern(u,l)&&o.push(p)}const f=new Set,h=l=>{for(const u of[...l])if(!f.has(u)){f.add(u);try{u(r)}catch(p){console.error(p);continue}}};h(c);for(const l of o)h(l)}isPattern(e){return e.includes("*")}normalizeTypeKey(e){return e.replace(/^\./,"")}splitPath(e){return this.normalizeTypeKey(e).split(".").filter(Boolean)}matchPattern(e,t){const r=this.splitPath(e),n=this.splitPath(t);let s=0,c=0,i=-1,o=0;for(;c<n.length;)if(s<r.length&&(r[s]==="*"||r[s]===n[c]))s++,c++;else if(s<r.length&&r[s]==="**")i=s,o=c,s++;else if(i!==-1)s=i+1,c=++o;else return!1;for(;s<r.length&&r[s]==="**";)s++;return s===r.length}clear(){this.handlers.clear(),this.patternHandlers.clear()}__introspect(){const e=[];for(const[t,r]of this.handlers)for(const[n,s]of r)s.length>0&&e.push({channel:t,type:n,count:s.length});for(const[t,r]of this.patternHandlers)for(const[n,s]of r)s.length>0&&e.push({channel:t,type:n,count:s.length});return e}}class z{constructor(e){d(this,"_reduce");this._reduce=e}reduce(e,t){return this._reduce(e,t)}}function g(a,e,t="",r=new Map){if(a===e)return[];if(typeof a!="object"||typeof e!="object"||a===null||e===null)return typeof a=="number"&&Number.isNaN(a)&&Number.isNaN(e)?[]:[t];if(a instanceof Date&&e instanceof Date)return a.getTime()===e.getTime()?[]:[t];if(a instanceof RegExp&&e instanceof RegExp)return a.source===e.source&&e.flags===a.flags?[]:[t];const n=a,s=e,c=r.get(n);if(c?.has(s))return[];const i=c??new Set;i.add(s),c||r.set(n,i);try{const o=Array.isArray(a),f=Array.isArray(e);if(o!==f)return[t];const h=[];if(o){const u=a,p=e;if(u.length!==p.length)return[t];for(let y=0;y<u.length;y++){const m=t?`${t}.${y}`:`${y}`;h.push(...g(u[y],p[y],m,r))}return h.filter(Boolean)}const l=new Set([...Object.keys(a),...Object.keys(e)]);for(const u of l){const p=t?`${t}.${u}`:u,y=Object.prototype.hasOwnProperty.call(a,u),m=Object.prototype.hasOwnProperty.call(e,u);if(!y||!m){h.push(p);continue}h.push(...g(a[u],e[u],p,r))}return h.filter(Boolean)}finally{i.delete(s),i.size===0&&r.delete(n)}}function E(a,e=new WeakSet){if(a===null||typeof a!="object"||e.has(a)||Object.isFrozen(a))return a;if(e.add(a),Array.isArray(a)){const t=a;for(let r=0;r<t.length;r++)t[r]=E(t[r],e);return Object.freeze(t)}for(const t of Object.getOwnPropertyNames(a)){const r=Object.getOwnPropertyDescriptor(a,t);!r||!("value"in r)||(a[t]=E(a[t],e))}for(const t of Object.getOwnPropertySymbols(a)){const r=Object.getOwnPropertyDescriptor(a,t);!r||!("value"in r)||(a[t]=E(a[t],e))}return Object.freeze(a)}function b(a){return process.env.NODE_ENV==="production"?a:E(a)}const w=100,S=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now();class v{constructor(e){d(this,"name");d(this,"middleware");d(this,"reducers");d(this,"state");d(this,"reducerBus");d(this,"connectorBus");d(this,"listeners",new Set);d(this,"effects",new Map);d(this,"patternEffects",new Set);d(this,"committedEventSubscribers",new Map);d(this,"uncommittedEventSubscribers",new Map);d(this,"allEventSubscribers",new Map);d(this,"sliceUnsubs",new Map);d(this,"patternReducers",new Map);d(this,"replayEnabled");d(this,"onEffectError");d(this,"reduceQueue",[]);d(this,"isReducing",!1);d(this,"instrumentObservers",new Set);d(this,"changedPathSink",null);d(this,"inFlightEffects",0);d(this,"processedEvents",new Map);d(this,"dedupCount",0);d(this,"effectMeta",new WeakMap);d(this,"dedupConfig");d(this,"eventCleanupTimer",null);if(this.name=e.name??"yoltra Store",this.reducerBus=new M,this.connectorBus=new P,this.middleware=[...e.middleware??[]],this.reducers={},this.state={},this.replayEnabled=e.devtools?.allowReplay??!1,this.onEffectError=e.onEffectError,this.dedupConfig={windowMs:e.dedupWindowMs??0,maxCacheSize:1e3},Object.entries(e.reducer).forEach(([t,r])=>{this.mountSlice(t,r,{preserveState:!1})}),e.effects?.length)for(const t of e.effects)this.registerEffect(t);this.dispose=this.dispose.bind(this),this.notifyEffects=this.notifyEffects.bind(this),this.forwardEvent=this.forwardEvent.bind(this),this.__applyExternalState=this.__applyExternalState.bind(this),this.__replayEvents=this.__replayEvents.bind(this),this.__devtoolsIntrospect=this.__devtoolsIntrospect.bind(this),this.mountSlice=this.mountSlice.bind(this),this.unmountSlice=this.unmountSlice.bind(this),this.getAtPath=this.getAtPath.bind(this),this.emit=this.emit.bind(this),this.subscribe=this.subscribe.bind(this),this.connect=this.connect.bind(this),this.onEffect=this.onEffect.bind(this),this.onEvent=this.onEvent.bind(this),this.getState=this.getState.bind(this),this.registerEffect=this.registerEffect.bind(this),this.registerMiddleware=this.registerMiddleware.bind(this),this.registerReducer=this.registerReducer.bind(this),this.replaceMiddleware=this.replaceMiddleware.bind(this),this.replaceEffects=this.replaceEffects.bind(this),this.replaceReducers=this.replaceReducers.bind(this),this.hotReplace=this.hotReplace.bind(this)}dispose(){this.eventCleanupTimer&&(clearInterval(this.eventCleanupTimer),this.eventCleanupTimer=null),this.processedEvents.clear(),this.effects.clear(),this.patternEffects.clear(),this.effectMeta=new WeakMap,this.listeners.clear(),this.committedEventSubscribers.clear(),this.uncommittedEventSubscribers.clear(),this.allEventSubscribers.clear(),this.instrumentObservers.clear(),this.connectorBus.clear(),this.reducerBus.clear(),this.patternReducers.clear(),this.sliceUnsubs.clear(),this.changedPathSink=null}fingerprint(e,t,r){const n=`${e}::${t}`;try{if(r==null)return`${n}::null`;if(typeof r!="object")return`${n}::${String(r)}`;const s=JSON.stringify(r);return`${n}::${s}`}catch{return`${n}::${Date.now()}::${Math.random()}`}}shouldDedupe(e,t){const r=Date.now(),n=this.processedEvents.get(e);return n!==void 0&&r-n<t?(this.dedupCount++,!0):(this.processedEvents.set(e,r),this.ensureCleanupTimer(),this.processedEvents.size>this.dedupConfig.maxCacheSize&&this.pruneProcessedEvents(r),!1)}ensureCleanupTimer(){this.eventCleanupTimer===null&&(this.eventCleanupTimer=setInterval(()=>{this.pruneProcessedEvents(Date.now())},5e3),this.eventCleanupTimer.unref?.())}pruneProcessedEvents(e){const t=Math.max(this.dedupConfig.windowMs,w),r=e-t*2;for(const[n,s]of this.processedEvents)s<r&&this.processedEvents.delete(n);this.processedEvents.size===0&&this.eventCleanupTimer!==null&&(clearInterval(this.eventCleanupTimer),this.eventCleanupTimer=null)}matchesWhen(e,t){return!e||"any"in e&&e.any===!0?!0:"keys"in e?e.keys.some(([r,n])=>t.channel===r&&t.type===n):"channel"in e?t.channel===e.channel:"channels"in e?e.channels.includes(t.channel):!1}getMiddlewareFunction(e){return typeof e=="function"?e:e.middleware}getMiddlewareWhen(e){if(typeof e!="function")return e.when}async notifyEffects(e){const t=`${String(e.channel)}::${String(e.type)}`,r=this.effects.get(t);if(r&&r.size>0)for(const n of[...r])try{await n(e,this.getState,this.emit)}catch(s){console.error("Effect error:",s),this.onEffectError?.(s,e)}for(const{effect:n,when:s}of this.patternEffects)if(this.matchesWhen(s,e))try{await n(e,this.getState,this.emit)}catch(c){console.error("Effect error:",c),this.onEffectError?.(c,e)}}notifyEventSubscribers(e,t){const r=`${String(e.channel)}::${String(e.type)}`,s=(t==="committed"?this.committedEventSubscribers:this.uncommittedEventSubscribers).get(r);if(s?.size)for(const i of[...s])this.invokeEventSubscriber(i,e,t);const c=this.allEventSubscribers.get(r);if(c?.size)for(const i of[...c])this.invokeEventSubscriber(i,e,t)}invokeEventSubscriber(e,t,r){try{const n=e(t,this.getState,this.emit,r);n&&typeof n.then=="function"&&n.catch(s=>console.error("Event subscription error:",s))}catch(n){console.error("Event subscription error:",n)}}forwardEvent(e,t){const r=this.state[e],n=this.reducers[e].reduce(r,t);if(r===n)return!1;const s=g(r,n).filter(Boolean);if(s.length===0)return!1;const c=b(n);if(this.state={...this.state,[e]:c},this.changedPathSink)for(const o of s)this.changedPathSink.push(o?`${e}.${o}`:e);const i=new Set;for(const o of s)for(const f of v.buildAncestorPaths(o))i.add(f);for(const o of i){const f=this.getAtPath(r,o),h=this.getAtPath(c,o);this.connectorBus.emit(e,o,{oldValue:f,newValue:h,path:o})}return!0}__devtoolsIntrospect(){const e=Object.keys(this.reducers).map(i=>{const o=this.patternReducers.get(i);return{name:i,when:o}}),t=[];for(const[i,o]of this.effects){if(o.size===0)continue;const[f,h]=i.split("::");for(const l of o){const u=this.effectMeta.get(l);t.push({channel:f,type:h,name:u?.name,description:u?.description})}}for(const i of this.patternEffects){const o=this.effectMeta.get(i.effect);t.push({channel:"*",type:"*",name:o?.name,description:o?.description})}const r=[];for(const i of this.middleware)typeof i=="function"?r.push({name:i.name||void 0}):r.push({name:i.meta?.name,description:i.meta?.description,when:i.when});const n=[];for(const i of this.connectorBus.__introspect())for(let o=0;o<i.count;o++)n.push({reducer:i.channel,property:i.type});const s=[];for(const[i,o]of this.committedEventSubscribers){if(o.size===0)continue;const[f,h]=i.split("::");for(let l=0;l<o.size;l++)s.push({channel:f,type:h,phase:"committed"})}for(const[i,o]of this.uncommittedEventSubscribers){if(o.size===0)continue;const[f,h]=i.split("::");for(let l=0;l<o.size;l++)s.push({channel:f,type:h,phase:"uncommitted"})}for(const[i,o]of this.allEventSubscribers){if(o.size===0)continue;const[f,h]=i.split("::");for(let l=0;l<o.size;l++)s.push({channel:f,type:h,phase:"all"})}const c=this.listeners.size;return{reducers:e,effects:t,middleware:r,atomic:n,event:s,coarse:c,dedupHits:this.dedupCount,queueDepth:this.reduceQueue.length+this.inFlightEffects}}__applyExternalState(e){if(!this.replayEnabled){console.warn("[yoltra] External state apply (time-travel) is disabled. Enable it with createStore({ devtools: { allowReplay: true } })");return}const t=this.state,r=e,n={...this.state};let s=!1;Object.keys(this.reducers).forEach(c=>{const i=t?.[c],o=r?.[c];if(o===void 0){process.env.NODE_ENV!=="production"&&console.warn(`[yoltra] External state is missing slice "${String(c)}"; retaining its current value. Time-travel snapshots should contain all slices.`);return}if(i===o)return;const f=b(o);n[c]=f,s=!0;const h=g(i,o).filter(Boolean);if(h.length===0)return;const l=new Set;for(const u of h)for(const p of v.buildAncestorPaths(u))l.add(p);for(const u of l){const p=this.getAtPath(i,u),y=this.getAtPath(f,u);this.connectorBus.emit(c,u,{oldValue:p,newValue:y,path:u})}}),s&&(this.state=n),s&&this.listeners.forEach(c=>c())}__replayEvents(e,t){if(!this.replayEnabled)throw new Error("[yoltra] Event replay is disabled. Enable it with createStore({ devtools: { allowReplay: true } })");this.__applyExternalState(e);for(const r of t){const n=r,s=this.state;this.reducerBus.emit(n.channel,n.type,n.payload);for(const[o,f]of this.patternReducers)this.matchesWhen(f,n)&&this.forwardEvent(o,n);const c=this.state,i=s!==c;this.notifyEventSubscribers(n,"committed"),i&&this.listeners.forEach(o=>o())}}async emit(e,t,r,n){const s=n?.dedupKey,c=this.dedupConfig.windowMs;if(c>0||s!==void 0){const h=s!==void 0&&c<=0?w:c,l=s!==void 0?`${e}::${t}::#${s}`:this.fingerprint(e,t,r);if(this.shouldDedupe(l,h))return}const i=crypto.randomUUID();let o;const f=new Promise(h=>{o=h});return this.reduceQueue.push({channel:e,type:t,payload:r,id:i,resolve:o}),this.drainReduce(),f}drainReduce(){if(!this.isReducing){this.isReducing=!0;try{for(;this.reduceQueue.length>0;){const{channel:e,type:t,payload:r,id:n,resolve:s}=this.reduceQueue.shift(),c={channel:e,type:t,payload:r,id:n},i=this.instrumentObservers.size>0,o=i?this.state:void 0,f=[];i&&(this.changedPathSink=f);const h=i?S():0;let l=!1;try{l=this.applyEventSync(c)}catch(u){console.error("Emit reduce error:",u)}finally{i&&(this.changedPathSink=null)}i&&this.emitInstrumentation(c,l,f,o,S()-h),this.runEventEffects(c,l,s)}}finally{this.isReducing=!1}}}applyEventSync(e){for(const n of this.middleware){const s=this.getMiddlewareWhen(n);if(!this.matchesWhen(s,e))continue;const c=this.getMiddlewareFunction(n);let i;try{i=c(this.state,e,this.emit)}catch(o){console.error("Middleware error:",o),i=!1}if(!i)return this.notifyEventSubscribers(e,"uncommitted"),!1}const t=this.state;this.reducerBus.emit(e.channel,e.type,e.payload);for(const[n,s]of this.patternReducers)this.matchesWhen(s,e)&&this.forwardEvent(n,e);const r=t!==this.state;return this.notifyEventSubscribers(e,"committed"),r&&this.listeners.forEach(n=>n()),!0}async runEventEffects(e,t,r){this.inFlightEffects++;try{t&&await this.notifyEffects(e)}catch(n){console.error("Effect error:",n)}finally{this.inFlightEffects--,r()}}instrument(e){return this.instrumentObservers.add(e),()=>{this.instrumentObservers.delete(e)}}emitInstrumentation(e,t,r,n,s){const c={},i={};for(const f of r)c[f]=this.getAtPath(n,f),i[f]=this.getAtPath(this.state,f);const o={event:{id:e.id,channel:e.channel,type:e.type,payload:e.payload},committed:t,changedPaths:r,prevValues:c,nextValues:i,reduceTimeMs:s};for(const f of[...this.instrumentObservers])try{f(o)}catch(h){console.error("Instrumentation observer error:",h)}}connect(e,t){return this.connectorBus.on(e.reducer,e.property,t)}onEvent(e,t,r,n="committed"){const s=`${e}::${String(t)}`,c=n==="committed"?this.committedEventSubscribers:n==="uncommitted"?this.uncommittedEventSubscribers:this.allEventSubscribers;return c.has(s)||c.set(s,new Set),c.get(s).add(r),()=>{const i=c.get(s);i&&(i.delete(r),i.size===0&&c.delete(s))}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}getState(){return this.state}registerMiddleware(e){return this.middleware.push(e),()=>{const t=this.middleware.indexOf(e);t!==-1&&this.middleware.splice(t,1)}}registerReducer(e,t){if(e in this.reducers)throw new Error(`Reducer ${e} already exists`);return this.mountSlice(e,t,{preserveState:!1}),this.listeners.forEach(r=>r()),()=>{this.unmountSlice(e,{deleteState:!0}),this.listeners.forEach(r=>r())}}registerEffect(e){const{effect:t,meta:r,when:n}=e,s=[];if(r&&this.effectMeta.set(t,r),n&&("any"in n&&n.any===!0||"channel"in n||"channels"in n)){const o={effect:t,when:n};return this.patternEffects.add(o),()=>{this.patternEffects.delete(o)}}const i=this.normalizeEventKeys(e);if(i.length===0&&!n&&!e.events){const o={effect:t,when:{any:!0}};return this.patternEffects.add(o),()=>{this.patternEffects.delete(o)}}for(const[o,f]of i){const h=`${String(o)}::${String(f)}`;this.effects.has(h)||this.effects.set(h,new Set),this.effects.get(h).add(t),s.push(()=>{const l=this.effects.get(h);l&&(l.delete(t),l.size===0&&this.effects.delete(h))})}return()=>{for(const o of s)o()}}onEffect(e,t,r){const n=async(s,c,i)=>{if(s.channel!==e||s.type!==t)return;const o=s;return r(o.payload,c,i,o)};return this.registerEffect({events:[[e,t]],effect:n})}replaceMiddleware(e){this.middleware.length=0;for(const t of e)this.middleware.push(t)}replaceEffects(e){this.effects.clear(),this.patternEffects.clear();for(const t of e)this.registerEffect(t)}replaceReducers(e,t={}){const r=t.preserveState!==!1,n=new Set(Object.keys(this.reducers)),s=Object.entries(e),c=new Set(s.map(([i])=>i));for(const i of n)c.has(i)||this.unmountSlice(i,{deleteState:!0});for(const[i,o]of s)n.has(i)?(this.unmountSlice(i,{deleteState:!1}),this.mountSlice(i,o,{preserveState:r})):this.mountSlice(i,o,{preserveState:!1})}hotReplace(e){e.middleware&&this.replaceMiddleware(e.middleware),e.effects&&this.replaceEffects(e.effects),e.reducer&&this.replaceReducers(e.reducer,{preserveState:e.preserveState})}mountSlice(e,t,r){const n=e,{events:s,reducer:c,state:i,when:o}=t;if(this.reducers[e]=new z(c),(!r.preserveState||this.state[n]===void 0)&&(this.state[n]=b(structuredClone(i))),o&&("any"in o&&o.any===!0||"channel"in o||"channels"in o)){this.patternReducers.set(e,o),this.sliceUnsubs.set(n,[]);return}const h=this.normalizeEventKeys(t);if(h.length===0&&!o&&!s){this.patternReducers.set(e,{any:!0}),this.sliceUnsubs.set(n,[]);return}const l=[];for(const[u,p]of h){const y=this.reducerBus.on(u,p,m=>{const O={channel:u,type:p,payload:m,id:crypto.randomUUID()};this.forwardEvent(e,O)});l.push(y)}this.sliceUnsubs.set(n,l)}unmountSlice(e,t){const r=e;this.patternReducers.delete(e);const n=this.sliceUnsubs.get(r);if(n){for(const s of n)try{s()}catch(c){console.error(`[Store error]: ${c}`)}this.sliceUnsubs.delete(r)}delete this.reducers[e],t.deleteState&&delete this.state[r]}normalizeEventKeys(e){if(e.when){const t=e.when;if("any"in t&&t.any===!0)return[];if("keys"in t)return t.keys;if("channel"in t)return[];if("channels"in t)return[]}return e.events?e.events:[]}getAtPath(e,t){if(!t)return e;const n=(t[0]==="."?t.slice(1):t).split(".");let s=e;for(const c of n){if(s==null)return;s=s[c]}return s}static buildAncestorPaths(e){if(!e)return[];const r=(e[0]==="."?e.slice(1):e).split("."),n=[];for(let s=0;s<r.length;s++)n.push(r.slice(0,s+1).join("."));return n}}function _(a){return new v({name:a.name,reducer:a.reducer??{},middleware:a.middleware??[],effects:a.effects??[],dedupWindowMs:a.dedupWindowMs,devtools:a.devtools,onEffectError:a.onEffectError})}const $=a=>(e,t)=>t.map(r=>[e,r]),x=()=>a=>a;exports.EventBus=M;exports.LooseEventBus=P;exports.Reducer=z;exports.Store=v;exports.createStore=_;exports.detectChangedProps=g;exports.eventKeys=x;exports.freezeState=E;exports.typedEvents=$;
10
+ "use strict";var K=Object.defineProperty;var W=(o,e,t)=>e in o?K(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var p=(o,e,t)=>W(o,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class A{constructor(){p(this,"handlers",new Map)}on(e,t,s){let n=this.handlers.get(e);n||(n=new Map,this.handlers.set(e,n));let i=n.get(t);return i||(i=new Set,n.set(t,i)),i.add(s),()=>this.off(e,t,s)}off(e,t,s){const n=this.handlers.get(e);if(!n)return;const i=n.get(t);i&&(i.delete(s),i.size===0&&n.delete(t),n.size===0&&this.handlers.delete(e))}emit(e,t,s,n){const i=this.handlers.get(e);if(!i)return;const d=i.get(t);if(!(!d||d.size===0))for(const a of[...d])try{a(s,n)}catch(r){console.error("EventBus handler error:",r)}}clear(){this.handlers.clear()}}class N{constructor(){p(this,"handlers",new Map);p(this,"patternHandlers",new Map);p(this,"patternIndex",new Map)}on(e,t,s){const n=String(t);if(this.isPattern(n)){const i=n;this.patternHandlers.has(e)||this.patternHandlers.set(e,new Map);const d=this.patternHandlers.get(e);return d.has(i)||(d.set(i,[]),this.indexPattern(e,i)),d.get(i).push(s),()=>this.offPattern(e,i,s)}else{const i=this.normalizeTypeKey(n);this.handlers.has(e)||this.handlers.set(e,new Map);const d=this.handlers.get(e);return d.has(i)||d.set(i,[]),d.get(i).push(s),()=>this.offExactNormalized(e,i,s)}}off(e,t,s){const n=this.normalizeTypeKey(String(t));this.offExactNormalized(e,n,s)}offExactNormalized(e,t,s){const n=this.handlers.get(e);if(!n)return;const i=n.get(t);if(!i)return;const d=i.indexOf(s);d!==-1&&i.splice(d,1),i.length===0&&n.delete(t),n.size===0&&this.handlers.delete(e)}offPattern(e,t,s){const n=this.patternHandlers.get(e);if(!n)return;const i=n.get(t);if(!i)return;const d=i.indexOf(s);d!==-1&&i.splice(d,1),i.length===0&&(n.delete(t),this.unindexPattern(e,t)),n.size===0&&(this.patternHandlers.delete(e),this.patternIndex.delete(e))}emit(e,t,s){const n=String(t),i=this.normalizeTypeKey(n),d=this.handlers.get(e)?.get(i)??[],a=this.matchingPatternHandlers(e,n),r=new Set,f=c=>{for(const u of[...c])if(!r.has(u)){r.add(u);try{u(s)}catch(l){console.error(l);continue}}};f(d);for(const c of a)f(c)}emitWith(e,t,s){const n=String(t),i=this.normalizeTypeKey(n),d=this.handlers.get(e)?.get(i)??[],a=this.matchingPatternHandlers(e,n);if(d.length===0&&a.length===0)return;const r=s(),f=new Set,c=u=>{for(const l of[...u])if(!f.has(l)){f.add(l);try{l(r)}catch(y){console.error(y);continue}}};c(d);for(const u of a)c(u)}isPattern(e){return e.includes("*")}normalizeTypeKey(e){return e.replace(/^\./,"")}splitPath(e){return this.normalizeTypeKey(e).split(".").filter(Boolean)}indexPattern(e,t){let s=this.patternIndex.get(e);s===void 0&&(s={byHead:new Map,anyHead:[]},this.patternIndex.set(e,s));const n=this.splitPath(t),i={pattern:t,segments:n},d=n[0];if(d===void 0||d==="*"||d==="**"){s.anyHead.push(i);return}const a=s.byHead.get(d);a===void 0?s.byHead.set(d,[i]):a.push(i)}unindexPattern(e,t){const s=this.patternIndex.get(e);if(s===void 0)return;const n=this.splitPath(t)[0],i=n===void 0||n==="*"||n==="**"?s.anyHead:s.byHead.get(n);if(i===void 0)return;const d=i.findIndex(a=>a.pattern===t);d!==-1&&i.splice(d,1),i.length===0&&i!==s.anyHead&&n!==void 0&&s.byHead.delete(n)}matchingPatternHandlers(e,t){const s=this.patternHandlers.get(e),n=this.patternIndex.get(e);if(s===void 0||s.size===0||n===void 0)return[];const i=this.splitPath(t),d=[],a=f=>{for(const c of f){if(!this.matchSegments(c.segments,i))continue;const u=s.get(c.pattern);u!==void 0&&d.push(u)}},r=i[0];if(r!==void 0){const f=n.byHead.get(r);f!==void 0&&a(f)}return a(n.anyHead),d}matchSegments(e,t){let s=0,n=0,i=-1,d=0;for(;n<t.length;)if(s<e.length&&(e[s]==="*"||e[s]===t[n]))s++,n++;else if(s<e.length&&e[s]==="**")i=s,d=n,s++;else if(i!==-1)s=i+1,n=++d;else return!1;for(;s<e.length&&e[s]==="**";)s++;return s===e.length}clear(){this.handlers.clear(),this.patternHandlers.clear(),this.patternIndex.clear()}__introspect(){const e=[];for(const[t,s]of this.handlers)for(const[n,i]of s)i.length>0&&e.push({channel:t,type:n,count:i.length});for(const[t,s]of this.patternHandlers)for(const[n,i]of s)i.length>0&&e.push({channel:t,type:n,count:i.length});return e}}class D{constructor(e){p(this,"_reduce");this._reduce=e}reduce(e,t){return this._reduce(e,t)}}const x=new Set;function M(o,e){const t=o?`${o}.${e}`:e;x.has(t)||(x.add(t),console.warn(`[yoltra] State key "${e}"${o?` under "${o}"`:""} contains a dot. Paths are dotted, so this key is indistinguishable from nested objects of the same name: a subscription to "${t}" may match the wrong value, and DevTools patches for it will address the wrong node. Rename the key, or nest it.`))}function k(o,e,t="",s=new Map){const n=[];return $(o,e,t,s,n),n}function $(o,e,t,s,n){if(o===e)return;if(typeof o!="object"||typeof e!="object"||o===null||e===null){if(typeof o=="number"&&Number.isNaN(o)&&Number.isNaN(e))return;n.push(t);return}if(o instanceof Date&&e instanceof Date){o.getTime()!==e.getTime()&&n.push(t);return}if(o instanceof RegExp&&e instanceof RegExp){(o.source!==e.source||e.flags!==o.flags)&&n.push(t);return}if(o instanceof Map||e instanceof Map){n.push(t);return}if(o instanceof Set||e instanceof Set){n.push(t);return}const i=o,d=e,a=s.get(i);if(a?.has(d))return;const r=a??new Set;r.add(d),a||s.set(i,r);try{const f=Array.isArray(o),c=Array.isArray(e);if(f!==c){n.push(t);return}if(f){const h=o,m=e;h.length!==m.length&&t&&n.push(t);const g=Math.min(h.length,m.length);for(let w=0;w<g;w++)h[w]!==m[w]&&$(h[w],m[w],t?`${t}.${w}`:`${w}`,s,n);for(let w=g;w<Math.max(h.length,m.length);w++)n.push(t?`${t}.${w}`:`${w}`);return}const u=Object.keys(o),l=Object.keys(e);if(u.length===0&&l.length===0){n.push(t);return}let y=u.length===l.length;if(y){for(let h=0;h<l.length;h++)if(!Object.prototype.hasOwnProperty.call(o,l[h])){y=!1;break}}if(y){for(const h of l)o[h]!==e[h]&&(process.env.NODE_ENV!=="production"&&h.includes(".")&&M(t,h),$(o[h],e[h],t?`${t}.${h}`:h,s,n));return}for(const h of l){const m=Object.prototype.hasOwnProperty.call(o,h);if(m&&o[h]===e[h])continue;process.env.NODE_ENV!=="production"&&h.includes(".")&&M(t,h);const g=t?`${t}.${h}`:h;if(!m){n.push(g);continue}$(o[h],e[h],g,s,n)}for(const h of u)Object.prototype.hasOwnProperty.call(e,h)||(process.env.NODE_ENV!=="production"&&h.includes(".")&&M(t,h),n.push(t?`${t}.${h}`:h))}finally{r.delete(d),r.size===0&&s.delete(i)}}function v(o,e=new WeakSet,t){if(o===null||typeof o!="object"||e.has(o)||(t!==void 0&&o===t.watch&&t.onFound(),Object.isFrozen(o)))return o;if(e.add(o),Array.isArray(o)){const s=o;for(let n=0;n<s.length;n++)s[n]=v(s[n],e,t);return Object.freeze(s)}for(const s of Object.getOwnPropertyNames(o)){const n=Object.getOwnPropertyDescriptor(o,s);!n||!("value"in n)||(o[s]=v(o[s],e,t))}for(const s of Object.getOwnPropertySymbols(o)){const n=Object.getOwnPropertyDescriptor(o,s);!n||!("value"in n)||(o[s]=v(o[s],e,t))}return Object.freeze(o)}function j(o,e){try{return structuredClone(e)}catch(t){throw new Error(`[yoltra] Initial state for slice "${String(o)}" could not be copied: ${t instanceof Error?t.message:String(t)}. State must be structured-cloneable — functions, class instances and DOM nodes are not. Keep behaviour out of state and store plain data.`)}}function P(o,e){return process.env.NODE_ENV==="production"?o:v(o,new WeakSet,e)}const z=100,I=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now();class S{constructor(e){p(this,"name");p(this,"middleware");p(this,"reducers");p(this,"state");p(this,"reducerBus");p(this,"connectorBus");p(this,"listeners",new Set);p(this,"effects",new Map);p(this,"patternEffects",new Set);p(this,"committedEventSubscribers",new Map);p(this,"uncommittedEventSubscribers",new Map);p(this,"allEventSubscribers",new Map);p(this,"sliceUnsubs",new Map);p(this,"patternReducers",new Map);p(this,"replayEnabled");p(this,"idFactory");p(this,"onEffectError");p(this,"onReducerError");p(this,"warnedPayloadAliases",new Set);p(this,"reduceQueue",[]);p(this,"isReducing",!1);p(this,"instrumentObservers",new Set);p(this,"changedPathSink",null);p(this,"inFlightEffects",0);p(this,"processedEvents",new Map);p(this,"dedupCount",0);p(this,"effectMeta",new WeakMap);p(this,"dedupConfig");p(this,"eventCleanupTimer",null);if(this.name=e.name??"yoltra Store",this.reducerBus=new A,this.connectorBus=new N,this.middleware=[...e.middleware??[]],this.reducers={},this.state={},this.replayEnabled=e.devtools?.allowReplay??!1,this.idFactory=e.idFactory??(()=>crypto.randomUUID()),this.onEffectError=e.onEffectError,this.onReducerError=e.onReducerError,this.dedupConfig={windowMs:e.dedupWindowMs??0,maxCacheSize:1e3},Object.entries(e.reducer).forEach(([t,s])=>{this.mountSlice(t,s,{preserveState:!1})}),e.effects?.length)for(const t of e.effects)this.registerEffect(t);this.dispose=this.dispose.bind(this),this.notifyEffects=this.notifyEffects.bind(this),this.forwardEvent=this.forwardEvent.bind(this),this.__applyExternalState=this.__applyExternalState.bind(this),this.__replayEvents=this.__replayEvents.bind(this),this.__devtoolsIntrospect=this.__devtoolsIntrospect.bind(this),this.mountSlice=this.mountSlice.bind(this),this.unmountSlice=this.unmountSlice.bind(this),this.getAtPath=this.getAtPath.bind(this),this.emit=this.emit.bind(this),this.subscribe=this.subscribe.bind(this),this.connect=this.connect.bind(this),this.onEffect=this.onEffect.bind(this),this.onEvent=this.onEvent.bind(this),this.getState=this.getState.bind(this),this.registerEffect=this.registerEffect.bind(this),this.registerMiddleware=this.registerMiddleware.bind(this),this.registerReducer=this.registerReducer.bind(this),this.replaceMiddleware=this.replaceMiddleware.bind(this),this.replaceEffects=this.replaceEffects.bind(this),this.replaceReducers=this.replaceReducers.bind(this),this.hotReplace=this.hotReplace.bind(this)}dispose(){this.eventCleanupTimer&&(clearInterval(this.eventCleanupTimer),this.eventCleanupTimer=null),this.processedEvents.clear(),this.effects.clear(),this.patternEffects.clear(),this.effectMeta=new WeakMap,this.listeners.clear(),this.committedEventSubscribers.clear(),this.uncommittedEventSubscribers.clear(),this.allEventSubscribers.clear(),this.instrumentObservers.clear(),this.connectorBus.clear(),this.reducerBus.clear(),this.patternReducers.clear(),this.sliceUnsubs.clear(),this.changedPathSink=null}fingerprint(e,t,s){const n=`${e}::${t}`;try{if(s==null)return`${n}::null`;if(typeof s!="object")return`${n}::${String(s)}`;const i=JSON.stringify(s);return`${n}::${i}`}catch{return`${n}::${Date.now()}::${Math.random()}`}}shouldDedupe(e,t){const s=Date.now(),n=this.processedEvents.get(e);return n!==void 0&&s-n<t?(this.dedupCount++,!0):(this.processedEvents.set(e,s),this.ensureCleanupTimer(),this.processedEvents.size>this.dedupConfig.maxCacheSize&&this.pruneProcessedEvents(s),!1)}ensureCleanupTimer(){this.eventCleanupTimer===null&&(this.eventCleanupTimer=setInterval(()=>{this.pruneProcessedEvents(Date.now())},5e3),this.eventCleanupTimer.unref?.())}pruneProcessedEvents(e){const t=Math.max(this.dedupConfig.windowMs,z),s=e-t*2;for(const[n,i]of this.processedEvents)i<s&&this.processedEvents.delete(n);this.processedEvents.size===0&&this.eventCleanupTimer!==null&&(clearInterval(this.eventCleanupTimer),this.eventCleanupTimer=null)}matchesWhen(e,t){return!e||"any"in e&&e.any===!0?!0:"keys"in e?e.keys.some(([s,n])=>t.channel===s&&t.type===n):"channel"in e?t.channel===e.channel:"channels"in e?e.channels.includes(t.channel):!1}getMiddlewareFunction(e){return typeof e=="function"?e:e.middleware}getMiddlewareWhen(e){if(typeof e!="function")return e.when}async notifyEffects(e){const t=`${String(e.channel)}::${String(e.type)}`,s=this.effects.get(t);if(s&&s.size>0)for(const n of[...s])try{await n(e,this.getState,this.emit)}catch(i){console.error("Effect error:",i),this.onEffectError?.(i,e)}for(const{effect:n,when:i}of this.patternEffects)if(this.matchesWhen(i,e))try{await n(e,this.getState,this.emit)}catch(d){console.error("Effect error:",d),this.onEffectError?.(d,e)}}notifyEventSubscribers(e,t){const s=`${String(e.channel)}::${String(e.type)}`,i=(t==="committed"?this.committedEventSubscribers:this.uncommittedEventSubscribers).get(s);if(i?.size)for(const a of[...i])this.invokeEventSubscriber(a,e,t);const d=this.allEventSubscribers.get(s);if(d?.size)for(const a of[...d])this.invokeEventSubscriber(a,e,t)}invokeEventSubscriber(e,t,s){try{const n=e(t,this.getState,this.emit,s);n&&typeof n.then=="function"&&n.catch(i=>console.error("Event subscription error:",i))}catch(n){console.error("Event subscription error:",n)}}forwardEventGuarded(e,t){try{return this.forwardEvent(e,t)}catch(s){return console.error(`Reducer error in slice "${e}":`,s),this.onReducerError?.(s,t,e),!1}}forwardEvent(e,t){const s=this.state[e],n=this.reducers[e].reduce(s,t);if(s===n)return!1;const i=k(s,n).filter(Boolean);if(i.length===0)return!1;const d=t.payload,a=process.env.NODE_ENV!=="production"&&d!==null&&typeof d=="object"?{watch:d,onFound:()=>{const c=`${e}:${t.channel}:${t.type}`;this.warnedPayloadAliases.has(c)||(this.warnedPayloadAliases.add(c),console.warn(`[yoltra] Slice "${e}" stored the payload of "${t.channel}/${t.type}" by reference. It is now frozen along with the rest of the state, so the emitter mutating it later will throw in development and silently corrupt state in production. Copy the payload in the reducer instead.`))}}:void 0,r=P(n,a);if(this.state={...this.state,[e]:r},this.changedPathSink)for(const c of i)this.changedPathSink.push(c?`${e}.${c}`:e);const f=new Set;for(const c of i)for(const u of S.buildAncestorPaths(c))f.add(u);for(const c of f)this.connectorBus.emitWith(e,c,()=>({oldValue:this.getAtPath(s,c),newValue:this.getAtPath(r,c),path:c}));return!0}__devtoolsIntrospect(){const e=Object.keys(this.reducers).map(a=>{const r=this.patternReducers.get(a);return{name:a,when:r}}),t=[];for(const[a,r]of this.effects){if(r.size===0)continue;const[f,c]=a.split("::");for(const u of r){const l=this.effectMeta.get(u);t.push({channel:f,type:c,name:l?.name,description:l?.description})}}for(const a of this.patternEffects){const r=this.effectMeta.get(a.effect);t.push({channel:"*",type:"*",name:r?.name,description:r?.description})}const s=[];for(const a of this.middleware)typeof a=="function"?s.push({name:a.name||void 0}):s.push({name:a.meta?.name,description:a.meta?.description,when:a.when});const n=[];for(const a of this.connectorBus.__introspect())for(let r=0;r<a.count;r++)n.push({reducer:a.channel,property:a.type});const i=[];for(const[a,r]of this.committedEventSubscribers){if(r.size===0)continue;const[f,c]=a.split("::");for(let u=0;u<r.size;u++)i.push({channel:f,type:c,phase:"committed"})}for(const[a,r]of this.uncommittedEventSubscribers){if(r.size===0)continue;const[f,c]=a.split("::");for(let u=0;u<r.size;u++)i.push({channel:f,type:c,phase:"uncommitted"})}for(const[a,r]of this.allEventSubscribers){if(r.size===0)continue;const[f,c]=a.split("::");for(let u=0;u<r.size;u++)i.push({channel:f,type:c,phase:"all"})}const d=this.listeners.size;return{reducers:e,effects:t,middleware:s,atomic:n,event:i,coarse:d,dedupHits:this.dedupCount,queueDepth:this.reduceQueue.length+this.inFlightEffects}}__applyExternalState(e){if(!this.replayEnabled)throw new Error("[yoltra] External state apply (time-travel) is disabled. Enable it with createStore({ devtools: { allowReplay: true } })");const t=this.state,s=e,n={...this.state};let i=!1;Object.keys(this.reducers).forEach(d=>{const a=t?.[d],r=s?.[d];if(r===void 0){process.env.NODE_ENV!=="production"&&console.warn(`[yoltra] External state is missing slice "${String(d)}"; retaining its current value. Time-travel snapshots should contain all slices.`);return}if(a===r)return;const f=P(r);n[d]=f,i=!0;const c=k(a,r).filter(Boolean);if(c.length===0)return;const u=new Set;for(const l of c)for(const y of S.buildAncestorPaths(l))u.add(y);for(const l of u){const y=this.getAtPath(a,l),h=this.getAtPath(f,l);this.connectorBus.emit(d,l,{oldValue:y,newValue:h,path:l})}}),i&&(this.state=n),i&&this.listeners.forEach(d=>d())}__replayEvents(e,t){if(!this.replayEnabled)throw new Error("[yoltra] Event replay is disabled. Enable it with createStore({ devtools: { allowReplay: true } })");this.__applyExternalState(e);for(const s of t){const n=s,i=this.state;this.reducerBus.emit(n.channel,n.type,n.payload,n);for(const[r,f]of this.patternReducers)this.matchesWhen(f,n)&&this.forwardEventGuarded(r,n);const d=this.state,a=i!==d;this.notifyEventSubscribers(n,"committed"),a&&this.listeners.forEach(r=>r())}}async emit(e,t,s,n){const i=n?.dedupKey,d=this.dedupConfig.windowMs;if(n?.skipDedup!==!0&&(d>0||i!==void 0)){const c=i!==void 0&&d<=0?z:d,u=i!==void 0?`${e}::${t}::#${i}`:this.fingerprint(e,t,s);if(this.shouldDedupe(u,c))return}const a=n?.id??this.idFactory();let r;const f=new Promise(c=>{r=c});return this.reduceQueue.push({channel:e,type:t,payload:s,id:a,meta:n?.meta,resolve:r}),this.drainReduce(),f}drainReduce(){if(!this.isReducing){this.isReducing=!0;try{for(;this.reduceQueue.length>0;){const{channel:e,type:t,payload:s,id:n,meta:i,resolve:d}=this.reduceQueue.shift(),a={channel:e,type:t,payload:s,id:n,...i!==void 0?{meta:i}:{}},r=this.instrumentObservers.size>0,f=r?this.state:void 0,c=r?[]:void 0;c!==void 0&&(this.changedPathSink=c);const u=r?I():0;let l=!1;try{l=this.applyEventSync(a)}catch(y){console.error("Emit reduce error:",y)}finally{r&&(this.changedPathSink=null)}r&&this.emitInstrumentation(a,l,c??[],f,I()-u),this.runEventEffects(a,l,d)}}finally{this.isReducing=!1}}}applyEventSync(e){for(const n of this.middleware){const i=this.getMiddlewareWhen(n);if(!this.matchesWhen(i,e))continue;const d=this.getMiddlewareFunction(n);let a;try{a=d(this.state,e,this.emit),process.env.NODE_ENV!=="production"&&typeof a?.then=="function"&&console.error(`[yoltra] Middleware for "${e.channel}/${e.type}" returned a Promise. Middleware is synchronous: a Promise is truthy, so this event was allowed without waiting and a "return false" inside it can never veto. Do the check synchronously, and put anything that must await in an effect.`)}catch(r){console.error("Middleware error:",r),a=!1}if(!a)return this.notifyEventSubscribers(e,"uncommitted"),!1}const t=this.state;this.reducerBus.emit(e.channel,e.type,e.payload,e);for(const[n,i]of this.patternReducers)this.matchesWhen(i,e)&&this.forwardEventGuarded(n,e);const s=t!==this.state;return this.notifyEventSubscribers(e,"committed"),s&&this.listeners.forEach(n=>n()),!0}async runEventEffects(e,t,s){this.inFlightEffects++;try{t&&await this.notifyEffects(e)}catch(n){console.error("Effect error:",n)}finally{this.inFlightEffects--,s()}}instrument(e){return this.instrumentObservers.add(e),()=>{this.instrumentObservers.delete(e)}}emitInstrumentation(e,t,s,n,i){const d={},a={};for(const f of s)d[f]=this.getAtPath(n,f),a[f]=this.getAtPath(this.state,f);const r={event:{id:e.id,channel:e.channel,type:e.type,payload:e.payload,...e.meta!==void 0?{meta:e.meta}:{}},committed:t,changedPaths:s,prevValues:d,nextValues:a,reduceTimeMs:i};for(const f of[...this.instrumentObservers])try{f(r)}catch(c){console.error("Instrumentation observer error:",c)}}connect(e,t){return this.connectorBus.on(e.reducer,e.property,t)}onEvent(e,t,s,n="committed"){const i=`${e}::${String(t)}`,d=n==="committed"?this.committedEventSubscribers:n==="uncommitted"?this.uncommittedEventSubscribers:this.allEventSubscribers;return d.has(i)||d.set(i,new Set),d.get(i).add(s),()=>{const a=d.get(i);a&&(a.delete(s),a.size===0&&d.delete(i))}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}getState(){return this.state}registerMiddleware(e){return this.middleware.push(e),()=>{const t=this.middleware.indexOf(e);t!==-1&&this.middleware.splice(t,1)}}registerReducer(e,t){if(e in this.reducers)throw new Error(`Reducer ${e} already exists`);return this.mountSlice(e,t,{preserveState:!1}),this.listeners.forEach(s=>s()),()=>{this.unmountSlice(e,{deleteState:!0}),this.listeners.forEach(s=>s())}}registerEffect(e){const{effect:t,meta:s,when:n}=e,i=[];if(s&&this.effectMeta.set(t,s),n&&("any"in n&&n.any===!0||"channel"in n||"channels"in n)){const r={effect:t,when:n};return this.patternEffects.add(r),()=>{this.patternEffects.delete(r)}}const a=this.normalizeEventKeys(e);if(a.length===0&&!n){const r={effect:t,when:{any:!0}};return this.patternEffects.add(r),()=>{this.patternEffects.delete(r)}}for(const[r,f]of a){const c=`${String(r)}::${String(f)}`;this.effects.has(c)||this.effects.set(c,new Set),this.effects.get(c).add(t),i.push(()=>{const u=this.effects.get(c);u&&(u.delete(t),u.size===0&&this.effects.delete(c))})}return()=>{for(const r of i)r()}}onEffect(e,t,s){const n=async(i,d,a)=>{if(i.channel!==e||i.type!==t)return;const r=i;return s(r.payload,d,a,r)};return this.registerEffect({when:{keys:[[e,t]]},effect:n})}replaceMiddleware(e){this.middleware.length=0;for(const t of e)this.middleware.push(t)}replaceEffects(e){this.effects.clear(),this.patternEffects.clear();for(const t of e)this.registerEffect(t)}replaceReducers(e,t={}){const s=t.preserveState!==!1,n=new Set(Object.keys(this.reducers)),i=Object.entries(e),d=new Set(i.map(([a])=>a));for(const a of n)d.has(a)||this.unmountSlice(a,{deleteState:!0});for(const[a,r]of i)n.has(a)?(this.unmountSlice(a,{deleteState:!1}),this.mountSlice(a,r,{preserveState:s})):this.mountSlice(a,r,{preserveState:!1})}hotReplace(e){e.middleware&&this.replaceMiddleware(e.middleware),e.effects&&this.replaceEffects(e.effects),e.reducer&&this.replaceReducers(e.reducer,{preserveState:e.preserveState})}mountSlice(e,t,s){const n=e,{reducer:i,state:d,when:a}=t;if(this.reducers[e]=new D(i),(!s.preserveState||this.state[n]===void 0)&&(this.state={...this.state,[n]:P(j(n,d))}),a&&("any"in a&&a.any===!0||"channel"in a||"channels"in a)){this.patternReducers.set(e,a),this.sliceUnsubs.set(n,[]);return}const f=this.normalizeEventKeys(t);if(f.length===0&&!a){this.patternReducers.set(e,{any:!0}),this.sliceUnsubs.set(n,[]);return}const c=[];for(const[u,l]of f){const y=this.reducerBus.on(u,l,(h,m)=>{const g=m??{channel:u,type:l,payload:h,id:this.idFactory()};this.forwardEventGuarded(e,g)});c.push(y)}this.sliceUnsubs.set(n,c)}unmountSlice(e,t){const s=e;this.patternReducers.delete(e);const n=this.sliceUnsubs.get(s);if(n){for(const i of n)try{i()}catch(d){console.error(`[Store error]: ${d}`)}this.sliceUnsubs.delete(s)}if(delete this.reducers[e],t.deleteState){const{[s]:i,...d}=this.state;this.state=d}}normalizeEventKeys(e){if(e.when){const t=e.when;if("keys"in t)return t.keys}return[]}getAtPath(e,t){if(!t)return e;const n=(t[0]==="."?t.slice(1):t).split(".");let i=e;for(const d of n){if(i==null)return;i=i[d]}return i}static buildAncestorPaths(e){if(!e)return[];const s=(e[0]==="."?e.slice(1):e).split("."),n=[];for(let i=0;i<s.length;i++)n.push(s.slice(0,i+1).join("."));return n}}function F(o){return new S({name:o.name,reducer:o.reducer??{},middleware:o.middleware??[],effects:o.effects??[],dedupWindowMs:o.dedupWindowMs,idFactory:o.idFactory,devtools:o.devtools,onEffectError:o.onEffectError,onReducerError:o.onReducerError})}const V=o=>(e,t)=>t.map(s=>[e,s]),U=()=>o=>o,R=new Set;function L(o){const e=String(o);R.has(e)||(R.add(e),console.warn(`[yoltra] Entity id "${e}" contains a dot. Paths are dotted, so a subscription to "entities.${e}" is indistinguishable from one to a nested object of the same name. Use ids without dots.`))}function G(o,e){if(o.length!==e.length)return e;for(let t=0;t<o.length;t++)if(o[t]!==e[t])return e;return o}function Q(o={}){const e=o.selectId??(r=>r.id),{sortComparer:t}=o,s=(r,f)=>{if(t===void 0)return f;const c=[...f].sort((u,l)=>{const y=r.entities[u],h=r.entities[l];return y===void 0||h===void 0?0:t(y,h)});return G(f,c)},n=(r,f,c)=>{const u={...r,entities:f,ids:c};return{...u,ids:s(u,c)}},i=(r,f,c)=>{let u=null,l=null;for(const y of f){const h=e(y);process.env.NODE_ENV!=="production"&&String(h).includes(".")&&L(h);const m=(u??r.entities)[h];if(m!==void 0&&c==="add")continue;const g=m!==void 0&&c==="upsert"?{...m,...y}:y;u??(u={...r.entities}),u[h]=g,m===void 0&&(l??(l=[...r.ids]),l.push(h))}return u===null?r:n(r,u,l??r.ids)},d=(r,f)=>{let c=null;for(const{id:u,changes:l}of f){const y=(c??r.entities)[u];y!==void 0&&(c??(c={...r.entities}),c[u]={...y,...l})}return c===null?r:n(r,c,r.ids)},a=(r,f)=>{const c=new Set(f.filter(l=>r.entities[l]!==void 0));if(c.size===0)return r;const u={...r.entities};for(const l of c)delete u[l];return n(r,u,r.ids.filter(l=>!c.has(l)))};return{getInitialState(r){const f={ids:[],entities:{}};return r===void 0?f:{...f,...r}},addOne:(r,f)=>i(r,[f],"add"),addMany:(r,f)=>i(r,f,"add"),setOne:(r,f)=>i(r,[f],"set"),setMany:(r,f)=>i(r,f,"set"),setAll:(r,f)=>{const c={},u=[];for(const l of f){const y=e(l);c[y]===void 0&&u.push(y),c[y]=l}return n(r,c,u)},updateOne:(r,f)=>d(r,[f]),updateMany:(r,f)=>d(r,f),upsertOne:(r,f)=>i(r,[f],"upsert"),upsertMany:(r,f)=>i(r,f,"upsert"),removeOne:(r,f)=>a(r,[f]),removeMany:(r,f)=>a(r,f),removeAll:r=>r.ids.length===0?r:n(r,{},[]),selectIds:r=>r.ids,selectEntities:r=>r.entities,selectAll:r=>r.ids.map(f=>r.entities[f]),selectById:(r,f)=>r.entities[f],selectTotal:r=>r.ids.length,idsPath:"ids",pathTo:(r,f)=>f===void 0?`entities.${r}`:`entities.${r}.${f}`,anyField:r=>`entities.*.${r}`}}const E="$yoltra";function O(o,e={}){const t=e.maxNodes??1e5,s=e.sanitize,n=[],i=new Map;let d=0,a=!1;function r(c,u){if(s!==void 0&&(c=s(u,c)),d+=1,d>t)return a=!0,{[E]:"unsupported",kind:"truncated"};switch(typeof c){case"undefined":return{[E]:"undefined"};case"bigint":return{[E]:"bigint",value:c.toString()};case"number":return Number.isNaN(c)?{[E]:"nan"}:c===1/0?{[E]:"infinity",sign:1}:c===-1/0?{[E]:"infinity",sign:-1}:c;case"function":case"symbol":return n.push(u),{[E]:"unsupported",kind:typeof c};case"string":case"boolean":return c}if(c===null)return null;const l=c,y=i.get(l);if(y!==void 0)return{[E]:"ref",path:y};if(i.set(l,u),c instanceof Date)return{[E]:"date",iso:c.toISOString()};if(c instanceof RegExp)return{[E]:"regexp",source:c.source,flags:c.flags};if(c instanceof Error)return{[E]:"error",name:c.name,message:c.message};if(c instanceof Map){const m=[];let g=0;for(const[w,H]of c)m.push([r(w,`${u}/@k${g}`),r(H,`${u}/${g}`)]),g+=1;return{[E]:"map",entries:m}}if(c instanceof Set){const m=[];let g=0;for(const w of c)m.push(r(w,`${u}/${g}`)),g+=1;return{[E]:"set",values:m}}if(Array.isArray(c))return c.map((m,g)=>r(m,`${u}/${g}`));const h={};for(const[m,g]of Object.entries(c))h[m]=r(g,`${u}/${B(m)}`);return E in h?{[E]:"escaped",value:h}:h}return{value:r(o,""),report:{truncated:a,unsupported:n}}}function T(o){const e=new Map,t=[];function s(d,a){if(d===null||typeof d!="object")return d;if(Array.isArray(d)){const f=[];return e.set(a,f),d.forEach((c,u)=>{if(_(c)){t.push({target:f,key:u,path:c.path}),f[u]=void 0;return}f[u]=s(c,`${a}/${u}`)}),f}if(typeof d[E]=="string"){const f=d;switch(f[E]){case"undefined":return;case"nan":return Number.NaN;case"infinity":return f.sign===1?1/0:-1/0;case"bigint":return BigInt(f.value);case"date":return new Date(f.iso);case"regexp":return new RegExp(f.source,f.flags);case"error":{const c=new Error(f.message);return c.name=f.name,c}case"unsupported":return;case"ref":return;case"map":{const c=new Map;return e.set(a,c),f.entries.forEach(([u,l],y)=>{c.set(s(u,`${a}/@k${y}`),s(l,`${a}/${y}`))}),c}case"set":{const c=new Set;return e.set(a,c),f.values.forEach((u,l)=>c.add(s(u,`${a}/${l}`))),c}case"escaped":return n(f.value,a);default:return}}return n(d,a)}function n(d,a){const r={};e.set(a,r);for(const[f,c]of Object.entries(d)){const u=`${a}/${B(f)}`;if(_(c)){t.push({target:r,key:f,path:c.path}),r[f]=void 0;continue}r[f]=s(c,u)}return r}const i=s(o,"");e.set("",i);for(const{target:d,key:a,path:r}of t)d[a]=e.get(r);return i}function _(o){return o!==null&&typeof o=="object"&&o[E]==="ref"&&typeof o.path=="string"}function B(o){return o.replace(/~/g,"~0").replace(/\//g,"~1")}function J(o,e,t={}){let s=t.maxNodes??1e5;for(let n=0;n<8;n+=1){const{value:i,report:d}=O(o,{...t,maxNodes:s});let a;try{a=JSON.stringify(i)?.length??0}catch{a=Number.POSITIVE_INFINITY}if(a<=e)return d.truncated?{value:i,truncated:!0,note:`State was too large to send in full; parts beyond ${s} nodes are omitted.`}:{value:i,truncated:!1};const r=Math.floor(s*e*.8/a);if(s=Math.max(1,Math.min(r,s-1)),s<=1&&n>0)break}return{value:{[E]:"unsupported",kind:"truncated"},truncated:!0,note:`State exceeds the ${e}-byte transport limit and could not be reduced to fit.`}}function b(o,e,t){o.onError?.(e,t)}async function Y(o){const e={slices:{},restored:!1};let t;try{t=o.source??await o.adapter.read(o.key)}catch(n){return b(o,n,"read"),e}if(t==null||t==="")return e;let s;try{s=T(JSON.parse(t))}catch(n){return b(o,n,"decode"),e}if(s===null||typeof s!="object"||typeof s.version!="number")return b(o,new Error("persisted payload is not a recognisable envelope"),"decode"),e;if(s.version!==o.version){if(o.migrate===void 0)return b(o,new Error(`persisted state is version ${s.version}, this build expects ${o.version}, and no migrate was supplied`),"migrate"),e;try{const n=o.migrate(s.slices,s.version);return n===null?e:{slices:n,restored:!0}}catch(n){return b(o,n,"migrate"),e}}return{slices:s.slices??{},restored:!0}}function q(o,e){if(!e.restored)return o;const t={};for(const[s,n]of Object.entries(o)){const i=e.slices[s];t[s]=i===void 0?n:{...n,state:i}}return t}function C(o,e){const t=o??{},s=e.slices===void 0?t:Object.fromEntries(e.slices.filter(n=>n in t).map(n=>[n,t[n]]));return JSON.stringify(O({version:e.version,slices:s}).value)}function X(o,e){const t=e.throttleMs??250,s=e.slices;let n=null,i=!1;const d=()=>{if(i){i=!1;try{const f=e.adapter.write(e.key,C(o.getState(),e));f instanceof Promise&&f.catch(c=>b(e,c,"write"))}catch(f){b(e,f,"write")}}},a=()=>{if(i=!0,t<=0){d();return}n===null&&(n=setTimeout(()=>{n=null,d()},t),n.unref?.())},r=o.instrument(f=>{if(s===void 0){a();return}(f.changedPaths??[]).some(u=>s.some(l=>u===l||u.startsWith(`${l}.`)))&&a()});return()=>{r(),n!==null&&(clearTimeout(n),n=null),d()}}function Z(o,e){return C(o.getState(),e)}function ee(o){return{read:e=>o.getItem(e),write:(e,t)=>o.setItem(e,t),remove:e=>o.removeItem(e)}}function te(o){const e=new Map(Object.entries(o??{}));return{read:t=>e.get(t)??null,write:(t,s)=>{e.set(t,s)},remove:t=>{e.delete(t)}}}exports.EventBus=A;exports.LooseEventBus=N;exports.Reducer=D;exports.Store=S;exports.createEntityAdapter=Q;exports.createMemoryAdapter=te;exports.createStore=F;exports.createWebStorageAdapter=ee;exports.decodeState=T;exports.dehydrate=Z;exports.detectChangedProps=k;exports.encodeState=O;exports.encodeStateBounded=J;exports.eventKeys=U;exports.freezeState=v;exports.hydrate=Y;exports.persist=X;exports.typedEvents=V;exports.withHydration=q;
11
11
  //# sourceMappingURL=yoltra.cjs.js.map