@yoltra/core 0.5.0 → 0.6.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.
@@ -1,6 +1,5 @@
1
- /**
2
- * @module @yoltra/core
3
- */
1
+ import { Rejection } from './store/rejection.js';
2
+ import { CallHandle, CallOptions } from './store/call.js';
4
3
  /**
5
4
  * A minimal "record of record" constraint for EventMaps.
6
5
  *
@@ -104,6 +103,29 @@ export interface Event<EM extends EventMapBase = EventMapBase, C extends keyof E
104
103
  * Absent entirely unless {@link EmitOptions.meta} was supplied. See {@link EventMeta}.
105
104
  */
106
105
  readonly meta?: EventMeta;
106
+ /**
107
+ * The `id` of the event whose handling caused this one, when there was one.
108
+ *
109
+ * @remarks
110
+ * Absent on a **root** event — one emitted by application code rather than by a middleware,
111
+ * subscriber or effect reacting to another event. Together with {@link Event.depth} this makes
112
+ * a cascade legible after the fact: without it, a runaway chain is a pile of unrelated events
113
+ * with no way to tell which caused which.
114
+ */
115
+ readonly parentId?: string;
116
+ /**
117
+ * How many events deep in a causal chain this one is. A root event is depth `0`; an event
118
+ * emitted while handling it is `1`, and so on.
119
+ *
120
+ * @remarks
121
+ * Absent on a root event rather than present as `0`, so an event emitted by application code
122
+ * stays byte-identical to one built before causality tracking existed — the same treatment
123
+ * {@link Event.meta} gets, and for the same reason: `Object.keys` and `toStrictEqual` are load
124
+ * bearing in consumer tests.
125
+ *
126
+ * This is the value {@link StoreSpec.maxReduceDepth} bounds.
127
+ */
128
+ readonly depth?: number;
107
129
  }
108
130
  /**
109
131
  * Generic "old → new" wrapper for fine-grained change notifications.
@@ -127,6 +149,20 @@ export interface Change<V = any> {
127
149
  newValue: V;
128
150
  /** Dotted path for fine-grained listeners; e.g., "data.items.0.title" */
129
151
  path?: string;
152
+ /**
153
+ * The `id` of the event that caused this change.
154
+ *
155
+ * @remarks
156
+ * A change used to be anonymous, so a subscriber that needed to know *why* a value moved had
157
+ * to mirror the cause into state and store it twice. Absent when the change did not come from
158
+ * an event — a DevTools time-travel snapshot, for instance — which is itself the signal that
159
+ * no event caused it.
160
+ */
161
+ eventId?: string;
162
+ /** Channel of the causing event. Absent for the same reason as {@link Change.eventId}. */
163
+ channel?: string;
164
+ /** Type of the causing event. Absent for the same reason as {@link Change.eventId}. */
165
+ type?: string;
130
166
  }
131
167
  /**
132
168
  * Emit function narrowed to the developer's EventMap.
@@ -143,6 +179,58 @@ export interface Change<V = any> {
143
179
  *
144
180
  * @public
145
181
  */
182
+ /**
183
+ * What an `emit` resolves to once its effects have run.
184
+ *
185
+ * @remarks
186
+ * `emit` used to resolve to `void`, so a caller could not tell "the reducer applied my write"
187
+ * from "the reducer looked at my write and returned the state unchanged". On a single-writer
188
+ * store that distinction is academic; on a contended one it is a lost update the API could not
189
+ * report.
190
+ *
191
+ * Deliberately does **not** carry the changed paths. Building that list costs a string
192
+ * concatenation per changed path on every emit, and almost no caller reads it — the same reason
193
+ * change notifications are built lazily. Instrumentation already provides them to the observers
194
+ * that do want them.
195
+ *
196
+ * @public
197
+ */
198
+ export interface EmitResult {
199
+ /**
200
+ * The event was not vetoed by middleware.
201
+ *
202
+ * @remarks
203
+ * Unchanged in meaning, and deliberately not narrowed to "state changed" — an event-only store
204
+ * commits every event and writes nothing, by construction.
205
+ */
206
+ readonly committed: boolean;
207
+ /** A reducer actually changed state. */
208
+ readonly written: boolean;
209
+ /** Present when a reducer refused the write. See {@link Rejection}. */
210
+ readonly rejected?: Rejection;
211
+ }
212
+ /**
213
+ * Options for {@link StoreInstance.connect}.
214
+ *
215
+ * @public
216
+ */
217
+ export interface ConnectOptions {
218
+ /**
219
+ * Deliver the current value once, immediately, before any change arrives.
220
+ *
221
+ * @remarks
222
+ * A subscription otherwise starts at "from now on", so a subscriber's first render has to read
223
+ * the path separately — the same path, spelled twice, which is one place for them to drift.
224
+ *
225
+ * The synthetic change has `oldValue: undefined` and no `eventId`, `channel` or `type`: no
226
+ * event caused it, and claiming one would be a lie a subscriber could act on.
227
+ *
228
+ * For a wildcard pattern the "current value" of a match set is not a thing, so the slice root
229
+ * is delivered with `path: ""`. React's hooks do not need this at all — `useSyncExternalStore`
230
+ * already reads a snapshot on mount — so it is aimed at imperative subscribers.
231
+ */
232
+ readonly immediate?: boolean;
233
+ }
146
234
  /**
147
235
  * Per-emit options.
148
236
  *
@@ -195,7 +283,7 @@ export interface EmitOptions {
195
283
  */
196
284
  skipDedup?: boolean;
197
285
  }
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>;
286
+ 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<EmitResult>;
199
287
  /**
200
288
  * Basic unsubscribe handle.
201
289
  *
@@ -235,6 +323,15 @@ export interface InstrumentedEvent<EM extends EventMapBase = EventMapBase> {
235
323
  nextValues: Record<string, unknown>;
236
324
  /** Wall-clock milliseconds spent in the synchronous reduce phase for this event. */
237
325
  reduceTimeMs: number;
326
+ /**
327
+ * Present when a reducer refused the write, carrying its reason.
328
+ *
329
+ * @remarks
330
+ * Distinct from `committed: false`, which means middleware vetoed the event before any reducer
331
+ * saw it. This is a reducer having considered the write and declined it — the two look
332
+ * identical in state and are entirely different in cause.
333
+ */
334
+ rejected?: Rejection;
238
335
  }
239
336
  /**
240
337
  * Observer for {@link StoreInstance.instrument}. Called once per emitted event
@@ -432,7 +529,104 @@ export type StoreSpec<R extends string, S extends Record<R, any>, EM extends Eve
432
529
  * @param slice - Name of the slice whose reducer threw.
433
530
  */
434
531
  onReducerError?: (error: unknown, event: EventUnion<EM>, slice: string) => void;
532
+ /**
533
+ * Maximum causal depth of an event chain before the store refuses to extend it.
534
+ *
535
+ * @remarks
536
+ * An event emitted while handling another is one deeper than its cause. Two reducers wired to
537
+ * each other, or an effect that emits the event its own reducer answers, climb this without
538
+ * bound — and the reduce queue drains synchronously, so in a browser that is a frozen tab with
539
+ * no error and no stack, and on a server a pinned core.
540
+ *
541
+ * **On by default**, because the whole point is that the failure mode does not require
542
+ * configuration to avoid. The default is far past any legitimate chain: an event caused by an
543
+ * event caused by an event is normal, sixty-four deep is a bug. Raise it if an application
544
+ * genuinely nests deeper, or set `Infinity` to opt out entirely and own the consequences.
545
+ *
546
+ * Breaching does not throw — see {@link StoreSpec.onCascade}.
547
+ *
548
+ * @default 64
549
+ */
550
+ maxReduceDepth?: number;
551
+ /**
552
+ * Maximum number of events one synchronous drain will process before refusing more.
553
+ *
554
+ * @remarks
555
+ * A drain processes one root event plus every event emitted *while it runs* — so this counts a
556
+ * single causal burst, not application traffic. A plain loop is unaffected: `emit` drains to
557
+ * completion before it returns, so `for (const row of rows) store.emit(…)` is a thousand drains
558
+ * of one event each, never one drain of a thousand.
559
+ *
560
+ * **Off by default** because a wide burst is not by itself a bug. One `sync` event whose
561
+ * subscriber fans out to five hundred `upsert`s is a legitimate shape, and a default low enough
562
+ * to catch a runaway would refuse it. Depth is what separates a cascade from a fan-out — a
563
+ * fan-out is wide and shallow, a cascade is narrow and deep — which is why
564
+ * {@link StoreSpec.maxReduceDepth} carries the default and this does not.
565
+ *
566
+ * Set it when a store's bursts are known to be bounded and an unexpectedly wide one is itself
567
+ * the symptom worth catching.
568
+ *
569
+ * @default undefined (no limit)
570
+ */
571
+ maxTransitionsPerDrain?: number;
572
+ /**
573
+ * Called when a ceiling is breached, instead of throwing.
574
+ *
575
+ * @remarks
576
+ * The offending emit is refused and the chain stops there; everything already committed
577
+ * stands. It does not throw, because the throw would surface in whichever frame happened to be
578
+ * emitting — a subscriber, an effect, a middleware — which is the same species of
579
+ * hard-to-attribute failure the ceiling exists to prevent. A cascade is a wiring bug, and this
580
+ * is where the wiring gets named.
581
+ *
582
+ * @param info - Which ceiling, the event that would have extended the chain, and its causal
583
+ * chain of ids, newest last.
584
+ */
585
+ onCascade?: (info: CascadeInfo<EM>) => void;
586
+ /**
587
+ * Called when a reducer refuses a write by returning {@link Rejected}.
588
+ *
589
+ * @remarks
590
+ * The caller learns of its own refusal from the `emit` result; this is for everyone else —
591
+ * logging, metrics, alerting on a rate of rejected writes. Shaped as a callback rather than a
592
+ * subscription for the same reason {@link StoreSpec.onReducerError} is: it is a rare global
593
+ * signal, not something several independent parties register and unregister for.
594
+ *
595
+ * A refusal is a normal outcome, not an error. It means a reducer considered the write and
596
+ * declined it — a stale compare-and-swap, an unmet precondition — and the event is rejected
597
+ * whole, so no slice writes.
598
+ *
599
+ * @param rejection - The refusal and its reason.
600
+ * @param event - The event that was refused.
601
+ * @param slice - Name of the slice whose reducer refused.
602
+ */
603
+ onRejected?: (rejection: Rejection, event: EventUnion<EM>, slice: string) => void;
435
604
  };
605
+ /**
606
+ * What {@link StoreSpec.onCascade} receives when a ceiling is breached.
607
+ *
608
+ * @typeParam EM - Event map.
609
+ *
610
+ * @public
611
+ */
612
+ export interface CascadeInfo<EM extends EventMapBase = EventMapBase> {
613
+ /** Which ceiling was hit. */
614
+ readonly limit: "maxReduceDepth" | "maxTransitionsPerDrain";
615
+ /** The configured value that was exceeded. */
616
+ readonly limitValue: number;
617
+ /** The event that was refused — the one that would have extended the chain. */
618
+ readonly event: EventUnion<EM>;
619
+ /** Causal depth the refused event would have had. */
620
+ readonly depth: number;
621
+ /**
622
+ * Ids from the root of the chain to the refused event's parent, newest last.
623
+ *
624
+ * @remarks
625
+ * Bounded to the most recent entries: a cascade is long by definition, and the useful part is
626
+ * the cycle at the end rather than the thousand identical hops before it.
627
+ */
628
+ readonly chain: readonly string[];
629
+ }
436
630
  /**
437
631
  * Public Store surface.
438
632
  *
@@ -474,7 +668,16 @@ export interface StoreInstance<R extends string = string, S extends Record<R, an
474
668
  connect(spec: {
475
669
  reducer: R;
476
670
  property: string;
477
- }, handler: (change: Change) => void): Unsubscribe;
671
+ }, handler: (change: Change) => void, options?: ConnectOptions): Unsubscribe;
672
+ /**
673
+ * Sends a request and waits for the reply, correlating the two automatically.
674
+ *
675
+ * @remarks
676
+ * Awaitable for the terminal reply, async-iterable for progress. See the implementation on
677
+ * {@link Store.call} for the full contract — correlation, backpressure, timeouts, and why it
678
+ * is a local primitive rather than something that federates.
679
+ */
680
+ call<C extends keyof EM & string, T extends keyof EM[C] & string>(channel: C, type: T, payload: EM[C][T], opts: CallOptions<EM>): CallHandle<EventUnion<EM>, EventUnion<EM>>;
478
681
  /**
479
682
  * Convenience helper to register an **effect** filtered by a single `(channel, type)` pair.
480
683
  *
@@ -664,7 +867,8 @@ export interface StoreInstance<R extends string = string, S extends Record<R, an
664
867
  * Use `when` for event targeting (preferred). The `events` property is
665
868
  * kept for backward compatibility but `when` is recommended for new code.
666
869
  *
667
- * @example Using `when` (recommended)
870
+ * @example
871
+ * Using `when` (recommended)
668
872
  * ```ts
669
873
  * const counterSpec: ReducerSpec<{ value: number }, MyEM> = {
670
874
  * state: { value: 0 },
@@ -706,7 +910,7 @@ export interface ReducerSpec<S = any, EM extends EventMapBase = EventMapBase> {
706
910
  *
707
911
  * @public
708
912
  */
709
- export type ReducerFunction<S = any, EM extends EventMapBase = EventMapBase> = (state: S, event: EventUnion<EM>) => S;
913
+ export type ReducerFunction<S = any, EM extends EventMapBase = EventMapBase> = (state: S, event: EventUnion<EM>) => S | Rejection;
710
914
  /**
711
915
  * Effect specification (stateless async event consumer).
712
916
  *
@@ -719,7 +923,8 @@ export type ReducerFunction<S = any, EM extends EventMapBase = EventMapBase> = (
719
923
  * - Effects are keyed by event for O(1) lookup (no scanning).
720
924
  * - Use `when` for event targeting (preferred over `events`).
721
925
  *
722
- * @example Using `when` (recommended)
926
+ * @example
927
+ * Using `when` (recommended)
723
928
  * ```ts
724
929
  * const logEffect: EffectSpec<AppState, MyEM> = {
725
930
  * when: { keys: eventKeys<MyEM>()([['ui', 'increment']]) },
@@ -1130,11 +1335,39 @@ export type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T ex
1130
1335
  *
1131
1336
  * - `'committed'`: Events that passed middleware and reached reducers (default)
1132
1337
  * - `'uncommitted'`: Events rejected by middleware
1338
+ * - `'written'`: Events that actually changed state
1133
1339
  * - `'all'`: Both committed and uncommitted events
1134
1340
  *
1341
+ * @remarks
1342
+ * `'committed'` means **not vetoed**, and always has. It fires for an event that passed
1343
+ * middleware whether or not any reducer wrote anything — including every event in a store with
1344
+ * no reducers at all, which is the shape a notification or analytics bus takes. Toasts,
1345
+ * animations and tracking depend on that, so it is not narrowed.
1346
+ *
1347
+ * `'written'` is the stricter fact, added rather than substituted: state changed. It fires
1348
+ * **after** the commit, so a subscriber reading `getState()` from it sees the new value — which
1349
+ * is what people tend to assume `'committed'` does.
1350
+ *
1351
+ * `'all'` deliberately stays `committed | uncommitted`. Folding `'written'` into it would hand
1352
+ * every existing `'all'` subscriber a second notification per written event and quietly double
1353
+ * their counts.
1354
+ *
1355
+ * @public
1356
+ */
1357
+ export type EventPhase = "committed" | "uncommitted" | "written" | "all";
1358
+ /**
1359
+ * The phases a handler is actually *told about*.
1360
+ *
1361
+ * @remarks
1362
+ * `'all'` is a subscription selector, not an outcome — nothing is ever delivered "in the all
1363
+ * phase". Naming the difference keeps the two from being conflated in a handler signature, which
1364
+ * is where they were previously spelled out by hand and drifted: adding `'written'` to
1365
+ * {@link EventPhase} left three copies in `@yoltra/react` still claiming a handler could only
1366
+ * ever see two phases, and the build failed on the mismatch.
1367
+ *
1135
1368
  * @public
1136
1369
  */
1137
- export type EventPhase = "committed" | "uncommitted" | "all";
1370
+ export type NotifiedPhase = Exclude<EventPhase, "all">;
1138
1371
  /**
1139
1372
  * Handler function for event subscriptions (receives full event union).
1140
1373
  *
@@ -1163,7 +1396,7 @@ export type EventPhase = "committed" | "uncommitted" | "all";
1163
1396
  *
1164
1397
  * @public
1165
1398
  */
1166
- export type EventSubscriptionHandler<S = any, EM extends EventMapBase = EventMapBase> = (event: EventUnion<EM>, getState: () => S, emit: Emit<EM>, phase: "committed" | "uncommitted") => void | Promise<void>;
1399
+ export type EventSubscriptionHandler<S = any, EM extends EventMapBase = EventMapBase> = (event: EventUnion<EM>, getState: () => S, emit: Emit<EM>, phase: NotifiedPhase) => void | Promise<void>;
1167
1400
  /**
1168
1401
  * Narrowed event subscription handler for specific `(channel, type)` pairs.
1169
1402
  * Provides better type inference when subscribing to a single event type.
@@ -1188,4 +1421,4 @@ export type EventSubscriptionHandler<S = any, EM extends EventMapBase = EventMap
1188
1421
  *
1189
1422
  * @public
1190
1423
  */
1191
- export type NarrowedEventHandler<S, EM extends EventMapBase, C extends keyof EM & string, T extends keyof EM[C] & string> = (event: Event<EM, C, T>, getState: () => S, emit: Emit<EM>, phase: "committed" | "uncommitted") => void | Promise<void>;
1424
+ export type NarrowedEventHandler<S, EM extends EventMapBase, C extends keyof EM & string, T extends keyof EM[C] & string> = (event: Event<EM, C, T>, getState: () => S, emit: Emit<EM>, phase: NotifiedPhase) => void | Promise<void>;
package/dist/yoltra.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @yoltra/core v0.5.0
2
+ * @yoltra/core v0.6.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 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 _{constructor(){p(this,"handlers",new Map)}on(e,t,n){let s=this.handlers.get(e);s||(s=new Map,this.handlers.set(e,s));let i=s.get(t);return i||(i=new Set,s.set(t,i)),i.add(n),()=>this.off(e,t,n)}off(e,t,n){const s=this.handlers.get(e);if(!s)return;const i=s.get(t);i&&(i.delete(n),i.size===0&&s.delete(t),s.size===0&&this.handlers.delete(e))}emit(e,t,n,s){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(n,s)}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,n){const s=String(t);if(this.isPattern(s)){const i=s;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(n),()=>this.offPattern(e,i,n)}else{const i=this.normalizeTypeKey(s);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(n),()=>this.offExactNormalized(e,i,n)}}off(e,t,n){const s=this.normalizeTypeKey(String(t));this.offExactNormalized(e,s,n)}offExactNormalized(e,t,n){const s=this.handlers.get(e);if(!s)return;const i=s.get(t);if(!i)return;const d=i.indexOf(n);d!==-1&&i.splice(d,1),i.length===0&&s.delete(t),s.size===0&&this.handlers.delete(e)}offPattern(e,t,n){const s=this.patternHandlers.get(e);if(!s)return;const i=s.get(t);if(!i)return;const d=i.indexOf(n);d!==-1&&i.splice(d,1),i.length===0&&(s.delete(t),this.unindexPattern(e,t)),s.size===0&&(this.patternHandlers.delete(e),this.patternIndex.delete(e))}emit(e,t,n){const s=String(t),i=this.normalizeTypeKey(s),d=this.handlers.get(e)?.get(i)??[],a=this.matchingPatternHandlers(e,s),r=new Set,f=c=>{for(const u of[...c])if(!r.has(u)){r.add(u);try{u(n)}catch(l){console.error(l);continue}}};f(d);for(const c of a)f(c)}emitWith(e,t,n){const s=String(t),i=this.normalizeTypeKey(s),d=this.handlers.get(e)?.get(i)??[],a=this.matchingPatternHandlers(e,s);if(d.length===0&&a.length===0)return;const r=n(),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 n=this.patternIndex.get(e);n===void 0&&(n={byHead:new Map,anyHead:[]},this.patternIndex.set(e,n));const s=this.splitPath(t),i={pattern:t,segments:s},d=s[0];if(d===void 0||d==="*"||d==="**"){n.anyHead.push(i);return}const a=n.byHead.get(d);a===void 0?n.byHead.set(d,[i]):a.push(i)}unindexPattern(e,t){const n=this.patternIndex.get(e);if(n===void 0)return;const s=this.splitPath(t)[0],i=s===void 0||s==="*"||s==="**"?n.anyHead:n.byHead.get(s);if(i===void 0)return;const d=i.findIndex(a=>a.pattern===t);d!==-1&&i.splice(d,1),i.length===0&&i!==n.anyHead&&s!==void 0&&n.byHead.delete(s)}matchingPatternHandlers(e,t){const n=this.patternHandlers.get(e),s=this.patternIndex.get(e);if(n===void 0||n.size===0||s===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=n.get(c.pattern);u!==void 0&&d.push(u)}},r=i[0];if(r!==void 0){const f=s.byHead.get(r);f!==void 0&&a(f)}return a(s.anyHead),d}matchSegments(e,t){let n=0,s=0,i=-1,d=0;for(;s<t.length;)if(n<e.length&&(e[n]==="*"||e[n]===t[s]))n++,s++;else if(n<e.length&&e[n]==="**")i=n,d=s,n++;else if(i!==-1)n=i+1,s=++d;else return!1;for(;n<e.length&&e[n]==="**";)n++;return n===e.length}clear(){this.handlers.clear(),this.patternHandlers.clear(),this.patternIndex.clear()}__introspect(){const e=[];for(const[t,n]of this.handlers)for(const[s,i]of n)i.length>0&&e.push({channel:t,type:s,count:i.length});for(const[t,n]of this.patternHandlers)for(const[s,i]of n)i.length>0&&e.push({channel:t,type:s,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="",n=new Map){const s=[];return $(o,e,t,n,s),s}function $(o,e,t,n,s){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;s.push(t);return}if(o instanceof Date&&e instanceof Date){o.getTime()!==e.getTime()&&s.push(t);return}if(o instanceof RegExp&&e instanceof RegExp){(o.source!==e.source||e.flags!==o.flags)&&s.push(t);return}if(o instanceof Map||e instanceof Map){s.push(t);return}if(o instanceof Set||e instanceof Set){s.push(t);return}const i=o,d=e,a=n.get(i);if(a?.has(d))return;const r=a??new Set;r.add(d),a||n.set(i,r);try{const f=Array.isArray(o),c=Array.isArray(e);if(f!==c){s.push(t);return}if(f){const h=o,m=e;h.length!==m.length&&t&&s.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}`,n,s);for(let w=g;w<Math.max(h.length,m.length);w++)s.push(t?`${t}.${w}`:`${w}`);return}const u=Object.keys(o),l=Object.keys(e);if(u.length===0&&l.length===0){s.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,n,s));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){s.push(g);continue}$(o[h],e[h],g,n,s)}for(const h of u)Object.prototype.hasOwnProperty.call(e,h)||(process.env.NODE_ENV!=="production"&&h.includes(".")&&M(t,h),s.push(t?`${t}.${h}`:h))}finally{r.delete(d),r.size===0&&n.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 n=o;for(let s=0;s<n.length;s++)n[s]=v(n[s],e,t);return Object.freeze(n)}for(const n of Object.getOwnPropertyNames(o)){const s=Object.getOwnPropertyDescriptor(o,n);!s||!("value"in s)||(o[n]=v(o[n],e,t))}for(const n of Object.getOwnPropertySymbols(o)){const s=Object.getOwnPropertyDescriptor(o,n);!s||!("value"in s)||(o[n]=v(o[n],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 _,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,n])=>{this.mountSlice(t,n,{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.warnedPayloadAliases.clear(),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,n){const s=`${e}::${t}`;try{if(n==null)return`${s}::null`;if(typeof n!="object")return`${s}::${String(n)}`;const i=JSON.stringify(n);return`${s}::${i}`}catch{return`${s}::${Date.now()}::${Math.random()}`}}shouldDedupe(e,t){const n=Date.now(),s=this.processedEvents.get(e);return s!==void 0&&n-s<t?(this.dedupCount++,!0):(this.processedEvents.set(e,n),this.ensureCleanupTimer(),this.processedEvents.size>this.dedupConfig.maxCacheSize&&this.pruneProcessedEvents(n),!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),n=e-t*2;for(const[s,i]of this.processedEvents)i<n&&this.processedEvents.delete(s);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(([n,s])=>t.channel===n&&t.type===s):"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)}`,n=this.effects.get(t);if(n&&n.size>0)for(const s of[...n])try{await s(e,this.getState,this.emit)}catch(i){console.error("Effect error:",i),this.onEffectError?.(i,e)}for(const{effect:s,when:i}of this.patternEffects)if(this.matchesWhen(i,e))try{await s(e,this.getState,this.emit)}catch(d){console.error("Effect error:",d),this.onEffectError?.(d,e)}}notifyEventSubscribers(e,t){const n=`${String(e.channel)}::${String(e.type)}`,i=(t==="committed"?this.committedEventSubscribers:this.uncommittedEventSubscribers).get(n);if(i?.size)for(const a of[...i])this.invokeEventSubscriber(a,e,t);const d=this.allEventSubscribers.get(n);if(d?.size)for(const a of[...d])this.invokeEventSubscriber(a,e,t)}invokeEventSubscriber(e,t,n){try{const s=e(t,this.getState,this.emit,n);s&&typeof s.then=="function"&&s.catch(i=>console.error("Event subscription error:",i))}catch(s){console.error("Event subscription error:",s)}}forwardEventGuarded(e,t){try{return this.forwardEvent(e,t)}catch(n){return console.error(`Reducer error in slice "${e}":`,n),this.onReducerError?.(n,t,e),!1}}forwardEvent(e,t){const n=this.state[e],s=this.reducers[e].reduce(n,t);if(n===s)return!1;const i=k(n,s);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(s,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){if(c===""){f.add("");continue}for(const u of S.buildAncestorPaths(c))f.add(u)}for(const c of f)this.connectorBus.emitWith(e,c,()=>({oldValue:this.getAtPath(n,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 n=[];for(const a of this.middleware)typeof a=="function"?n.push({name:a.name||void 0}):n.push({name:a.meta?.name,description:a.meta?.description,when:a.when});const s=[];for(const a of this.connectorBus.__introspect())for(let r=0;r<a.count;r++)s.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:n,atomic:s,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,n=e,s={...this.state};let i=!1;Object.keys(this.reducers).forEach(d=>{const a=t?.[d],r=n?.[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);s[d]=f,i=!0;const c=k(a,r);if(c.length===0)return;const u=new Set;for(const l of c){if(l===""){u.add("");continue}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=s),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 n of t){const s=n,i=this.state;this.reducerBus.emit(s.channel,s.type,s.payload,s);for(const[r,f]of this.patternReducers)this.matchesWhen(f,s)&&this.forwardEventGuarded(r,s);const d=this.state,a=i!==d;this.notifyEventSubscribers(s,"committed"),a&&this.listeners.forEach(r=>r())}}async emit(e,t,n,s){const i=s?.dedupKey,d=this.dedupConfig.windowMs;if(s?.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,n);if(this.shouldDedupe(u,c))return}const a=s?.id??this.idFactory();let r;const f=new Promise(c=>{r=c});return this.reduceQueue.push({channel:e,type:t,payload:n,id:a,meta:s?.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:n,id:s,meta:i,resolve:d}=this.reduceQueue.shift(),a={channel:e,type:t,payload:n,id:s,...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 s of this.middleware){const i=this.getMiddlewareWhen(s);if(!this.matchesWhen(i,e))continue;const d=this.getMiddlewareFunction(s);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[s,i]of this.patternReducers)this.matchesWhen(i,e)&&this.forwardEventGuarded(s,e);const n=t!==this.state;return this.notifyEventSubscribers(e,"committed"),n&&this.listeners.forEach(s=>s()),!0}async runEventEffects(e,t,n){this.inFlightEffects++;try{t&&await this.notifyEffects(e)}catch(s){console.error("Effect error:",s)}finally{this.inFlightEffects--,n()}}instrument(e){return this.instrumentObservers.add(e),()=>{this.instrumentObservers.delete(e)}}emitInstrumentation(e,t,n,s,i){const d={},a={};for(const f of n)d[f]=this.getAtPath(s,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:n,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,n,s="committed"){const i=`${e}::${String(t)}`,d=s==="committed"?this.committedEventSubscribers:s==="uncommitted"?this.uncommittedEventSubscribers:this.allEventSubscribers;return d.has(i)||d.set(i,new Set),d.get(i).add(n),()=>{const a=d.get(i);a&&(a.delete(n),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(Object.prototype.hasOwnProperty.call(this.reducers,e))throw new Error(`Reducer ${e} already exists`);return this.mountSlice(e,t,{preserveState:!1}),this.listeners.forEach(n=>n()),()=>{this.unmountSlice(e,{deleteState:!0}),this.listeners.forEach(n=>n())}}registerEffect(e){const{effect:t,meta:n,when:s}=e,i=[];if(n&&this.effectMeta.set(t,n),s&&("any"in s&&s.any===!0||"channel"in s||"channels"in s)){const r={effect:t,when:s};return this.patternEffects.add(r),()=>{this.patternEffects.delete(r)}}const a=this.normalizeEventKeys(e);if(a.length===0&&!s){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,n){const s=async(i,d,a)=>{if(i.channel!==e||i.type!==t)return;const r=i;return n(r.payload,d,a,r)};return this.registerEffect({when:{keys:[[e,t]]},effect:s})}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 n=t.preserveState!==!1,s=new Set(Object.keys(this.reducers)),i=Object.entries(e),d=new Set(i.map(([a])=>a));for(const a of s)d.has(a)||this.unmountSlice(a,{deleteState:!0});for(const[a,r]of i)s.has(a)?(this.unmountSlice(a,{deleteState:!1}),this.mountSlice(a,r,{preserveState:n})):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,n){const s=e,{reducer:i,state:d,when:a}=t;if(this.reducers[e]=new D(i),(!n.preserveState||this.state[s]===void 0)&&(this.state={...this.state,[s]:P(j(s,d))}),a&&("any"in a&&a.any===!0||"channel"in a||"channels"in a)){this.patternReducers.set(e,a),this.sliceUnsubs.set(s,[]);return}const f=this.normalizeEventKeys(t);if(f.length===0&&!a){this.patternReducers.set(e,{any:!0}),this.sliceUnsubs.set(s,[]);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(s,c)}unmountSlice(e,t){const n=e;this.patternReducers.delete(e);const s=this.sliceUnsubs.get(n);if(s){for(const i of s)try{i()}catch(d){console.error(`[Store error]: ${d}`)}this.sliceUnsubs.delete(n)}if(delete this.reducers[e],t.deleteState){const{[n]: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 s=(t[0]==="."?t.slice(1):t).split(".");let i=e;for(const d of s){if(i==null)return;i=i[d]}return i}static buildAncestorPaths(e){if(!e)return[];const n=(e[0]==="."?e.slice(1):e).split("."),s=[];for(let i=0;i<n.length;i++)s.push(n.slice(0,i+1).join("."));return s}}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(n=>[e,n]),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,n=(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)},s=(r,f,c)=>{const u={...r,entities:f,ids:c};return{...u,ids:n(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:s(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:s(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 s(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 s(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:s(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,n=e.sanitize,s=[],i=new Map;let d=0,a=!1;function r(c,u){if(n!==void 0&&(c=n(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 s.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}/${C(m)}`);return E in h?{[E]:"escaped",value:h}:h}return{value:r(o,""),report:{truncated:a,unsupported:s}}}function T(o){const e=new Map,t=[];function n(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(A(c)){t.push({target:f,key:u,path:c.path}),f[u]=void 0;return}f[u]=n(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(n(u,`${a}/@k${y}`),n(l,`${a}/${y}`))}),c}case"set":{const c=new Set;return e.set(a,c),f.values.forEach((u,l)=>c.add(n(u,`${a}/${l}`))),c}case"escaped":return s(f.value,a);default:return}}return s(d,a)}function s(d,a){const r={};e.set(a,r);for(const[f,c]of Object.entries(d)){const u=`${a}/${C(f)}`;if(A(c)){t.push({target:r,key:f,path:c.path}),r[f]=void 0;continue}r[f]=n(c,u)}return r}const i=n(o,"");e.set("",i);for(const{target:d,key:a,path:r}of t)d[a]=e.get(r);return i}function A(o){return o!==null&&typeof o=="object"&&o[E]==="ref"&&typeof o.path=="string"}function C(o){return o.replace(/~/g,"~0").replace(/\//g,"~1")}function J(o,e,t={}){let n=t.maxNodes??1e5;for(let s=0;s<8;s+=1){const{value:i,report:d}=O(o,{...t,maxNodes:n});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 ${n} nodes are omitted.`}:{value:i,truncated:!1};const r=Math.floor(n*e*.8/a);if(n=Math.max(1,Math.min(r,n-1)),n<=1&&s>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(s){return b(o,s,"read"),e}if(t==null||t==="")return e;let n;try{n=T(JSON.parse(t))}catch(s){return b(o,s,"decode"),e}if(n===null||typeof n!="object"||typeof n.version!="number")return b(o,new Error("persisted payload is not a recognisable envelope"),"decode"),e;if(n.version!==o.version){if(o.migrate===void 0)return b(o,new Error(`persisted state is version ${n.version}, this build expects ${o.version}, and no migrate was supplied`),"migrate"),e;try{const s=o.migrate(n.slices,n.version);return s===null?e:{slices:s,restored:!0}}catch(s){return b(o,s,"migrate"),e}}return{slices:n.slices??{},restored:!0}}function q(o,e){if(!e.restored)return o;const t={};for(const[n,s]of Object.entries(o)){const i=e.slices[n];t[n]=i===void 0?s:{...s,state:i}}return t}function B(o,e){const t=o??{},n=e.slices===void 0?t:Object.fromEntries(e.slices.filter(s=>s in t).map(s=>[s,t[s]]));return JSON.stringify(O({version:e.version,slices:n}).value)}function X(o,e){const t=e.throttleMs??250,n=e.slices;let s=null,i=!1;const d=()=>{if(i){i=!1;try{const f=e.adapter.write(e.key,B(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}s===null&&(s=setTimeout(()=>{s=null,d()},t),s.unref?.())},r=o.instrument(f=>{if(n===void 0){a();return}(f.changedPaths??[]).some(u=>n.some(l=>u===l||u.startsWith(`${l}.`)))&&a()});return()=>{r(),s!==null&&(clearTimeout(s),s=null),d()}}function Z(o,e){return B(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,n)=>{e.set(t,n)},remove:t=>{e.delete(t)}}}exports.EventBus=_;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;
10
+ "use strict";var G=Object.defineProperty;var J=(c,e,t)=>e in c?G(c,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[e]=t;var p=(c,e,t)=>J(c,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class B{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 r=n.get(t);return r||(r=new Set,n.set(t,r)),r.add(s),()=>this.off(e,t,s)}off(e,t,s){const n=this.handlers.get(e);if(!n)return;const r=n.get(t);r&&(r.delete(s),r.size===0&&n.delete(t),n.size===0&&this.handlers.delete(e))}emit(e,t,s,n){const r=this.handlers.get(e);if(!r)return;const o=r.get(t);if(!(!o||o.size===0))for(const d of[...o])try{d(s,n)}catch(i){console.error("EventBus handler error:",i)}}clear(){this.handlers.clear()}}class H{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 r=n;this.patternHandlers.has(e)||this.patternHandlers.set(e,new Map);const o=this.patternHandlers.get(e);return o.has(r)||(o.set(r,[]),this.indexPattern(e,r)),o.get(r).push(s),()=>this.offPattern(e,r,s)}else{const r=this.normalizeTypeKey(n);this.handlers.has(e)||this.handlers.set(e,new Map);const o=this.handlers.get(e);return o.has(r)||o.set(r,[]),o.get(r).push(s),()=>this.offExactNormalized(e,r,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 r=n.get(t);if(!r)return;const o=r.indexOf(s);o!==-1&&r.splice(o,1),r.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 r=n.get(t);if(!r)return;const o=r.indexOf(s);o!==-1&&r.splice(o,1),r.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),r=this.normalizeTypeKey(n),o=this.handlers.get(e)?.get(r)??[],d=this.matchingPatternHandlers(e,n),i=new Set,a=l=>{for(const u of[...l])if(!i.has(u)){i.add(u);try{u(s)}catch(f){console.error(f);continue}}};a(o);for(const l of d)a(l)}emitWith(e,t,s){const n=String(t),r=this.normalizeTypeKey(n),o=this.handlers.get(e)?.get(r)??[],d=this.matchingPatternHandlers(e,n);if(o.length===0&&d.length===0)return;const i=s(),a=new Set,l=u=>{for(const f of[...u])if(!a.has(f)){a.add(f);try{f(i)}catch(m){console.error(m);continue}}};l(o);for(const u of d)l(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),r={pattern:t,segments:n},o=n[0];if(o===void 0||o==="*"||o==="**"){s.anyHead.push(r);return}const d=s.byHead.get(o);d===void 0?s.byHead.set(o,[r]):d.push(r)}unindexPattern(e,t){const s=this.patternIndex.get(e);if(s===void 0)return;const n=this.splitPath(t)[0],r=n===void 0||n==="*"||n==="**"?s.anyHead:s.byHead.get(n);if(r===void 0)return;const o=r.findIndex(d=>d.pattern===t);o!==-1&&r.splice(o,1),r.length===0&&r!==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 r=this.splitPath(t),o=[],d=a=>{for(const l of a){if(!this.matchSegments(l.segments,r))continue;const u=s.get(l.pattern);u!==void 0&&o.push(u)}},i=r[0];if(i!==void 0){const a=n.byHead.get(i);a!==void 0&&d(a)}return d(n.anyHead),o}matchSegments(e,t){let s=0,n=0,r=-1,o=0;for(;n<t.length;)if(s<e.length&&(e[s]==="*"||e[s]===t[n]))s++,n++;else if(s<e.length&&e[s]==="**")r=s,o=n,s++;else if(r!==-1)s=r+1,n=++o;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,r]of s)r.length>0&&e.push({channel:t,type:n,count:r.length});for(const[t,s]of this.patternHandlers)for(const[n,r]of s)r.length>0&&e.push({channel:t,type:n,count:r.length});return e}}class W{constructor(e){p(this,"_reduce");this._reduce=e}reduce(e,t){return this._reduce(e,t)}}const D=new Set;function x(c,e){const t=c?`${c}.${e}`:e;D.has(t)||(D.add(t),console.warn(`[yoltra] State key "${e}"${c?` under "${c}"`:""} 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 T(c,e,t="",s=new Map){const n=[];return R(c,e,t,s,n),n}function R(c,e,t,s,n){if(c===e)return;if(typeof c!="object"||typeof e!="object"||c===null||e===null){if(typeof c=="number"&&Number.isNaN(c)&&Number.isNaN(e))return;n.push(t);return}if(c instanceof Date&&e instanceof Date){c.getTime()!==e.getTime()&&n.push(t);return}if(c instanceof RegExp&&e instanceof RegExp){(c.source!==e.source||e.flags!==c.flags)&&n.push(t);return}if(c instanceof Map||e instanceof Map){n.push(t);return}if(c instanceof Set||e instanceof Set){n.push(t);return}const r=c,o=e,d=s.get(r);if(d?.has(o))return;const i=d??new Set;i.add(o),d||s.set(r,i);try{const a=Array.isArray(c),l=Array.isArray(e);if(a!==l){n.push(t);return}if(a){const h=c,y=e;h.length!==y.length&&t&&n.push(t);const g=Math.min(h.length,y.length);for(let E=0;E<g;E++)h[E]!==y[E]&&R(h[E],y[E],t?`${t}.${E}`:`${E}`,s,n);for(let E=g;E<Math.max(h.length,y.length);E++)n.push(t?`${t}.${E}`:`${E}`);return}const u=Object.keys(c),f=Object.keys(e);if(u.length===0&&f.length===0){n.push(t);return}let m=u.length===f.length;if(m){for(let h=0;h<f.length;h++)if(!Object.prototype.hasOwnProperty.call(c,f[h])){m=!1;break}}if(m){for(const h of f)c[h]!==e[h]&&(process.env.NODE_ENV!=="production"&&h.includes(".")&&x(t,h),R(c[h],e[h],t?`${t}.${h}`:h,s,n));return}for(const h of f){const y=Object.prototype.hasOwnProperty.call(c,h);if(y&&c[h]===e[h])continue;process.env.NODE_ENV!=="production"&&h.includes(".")&&x(t,h);const g=t?`${t}.${h}`:h;if(!y){n.push(g);continue}R(c[h],e[h],g,s,n)}for(const h of u)Object.prototype.hasOwnProperty.call(e,h)||(process.env.NODE_ENV!=="production"&&h.includes(".")&&x(t,h),n.push(t?`${t}.${h}`:h))}finally{i.delete(o),i.size===0&&s.delete(r)}}function k(c,e=new WeakSet,t){if(c===null||typeof c!="object"||e.has(c)||(t!==void 0&&c===t.watch&&t.onFound(),Object.isFrozen(c)))return c;if(e.add(c),Array.isArray(c)){const s=c;for(let n=0;n<s.length;n++)s[n]=k(s[n],e,t);return Object.freeze(s)}for(const s of Object.getOwnPropertyNames(c)){const n=Object.getOwnPropertyDescriptor(c,s);!n||!("value"in n)||(c[s]=k(c[s],e,t))}for(const s of Object.getOwnPropertySymbols(c)){const n=Object.getOwnPropertyDescriptor(c,s);!n||!("value"in n)||(c[s]=k(c[s],e,t))}return Object.freeze(c)}const K=Symbol.for("yoltra.rejected");function q(c){return{[K]:!0,reason:c}}function F(c){return typeof c=="object"&&c!==null&&c[K]===!0}class Y{constructor(e){p(this,"highWaterMark");p(this,"buffer",[]);p(this,"takers",[]);p(this,"putters",[]);p(this,"consuming",!1);p(this,"ended",!1);p(this,"closed",!1);p(this,"dropped",0);this.highWaterMark=e}get droppedCount(){return this.dropped}beginConsuming(){this.consuming=!0}put(e){if(this.closed||this.ended)return Promise.resolve();const t=this.takers.shift();return t!==void 0?(t({value:e,done:!1}),Promise.resolve()):this.buffer.length<this.highWaterMark?(this.buffer.push(e),Promise.resolve()):this.consuming?new Promise(s=>{this.putters.push({item:e,release:s})}):(this.dropped++,Promise.resolve())}take(){this.consuming=!0;const e=this.buffer.shift();if(e!==void 0){const s=this.putters.shift();return s!==void 0&&(this.buffer.push(s.item),s.release()),Promise.resolve({value:e,done:!1})}const t=this.putters.shift();return t!==void 0?(t.release(),Promise.resolve({value:t.item,done:!1})):this.closed||this.ended?Promise.resolve({value:void 0,done:!0}):new Promise(s=>{this.takers.push(s)})}end(){if(this.ended||this.closed)return;this.ended=!0;let e=this.putters.shift();for(;e!==void 0;)this.buffer.push(e.item),e.release(),e=this.putters.shift();let t=this.takers.shift();for(;t!==void 0;){const s=this.buffer.shift();t(s!==void 0?{value:s,done:!1}:{value:void 0,done:!0}),t=this.takers.shift()}}close(){if(this.closed)return;this.closed=!0,this.buffer.length=0;let e=this.takers.shift();for(;e!==void 0;)e({value:void 0,done:!0}),e=this.takers.shift();let t=this.putters.shift();for(;t!==void 0;)t.release(),t=this.putters.shift()}}class U extends Error{constructor(t,s,n){super(`[yoltra] call to "${t}/${s}" saw no correlated reply for ${n}ms. The timeout is idle rather than total, so this means the responder went quiet, not that it was slow. Check that something handles "${t}/${s}" and that its reply is emitted through the \`emit\` it was handed — a reply emitted from an unrelated context carries no causal link, and needs an explicit correlationId instead.`);p(this,"channel");p(this,"type");p(this,"idleMs");this.name="CallTimeoutError",this.channel=t,this.type=s,this.idleMs=n}}class I extends Error{constructor(e){super(`[yoltra] call aborted: ${e}`),this.name="CallAbortedError"}}function X(c){const[e,t]=c;if(t===void 0)return{channel:e,isTerminal:()=>!0};if(typeof t=="string")return{channel:e,isTerminal:n=>n===t};const s=new Set(t);return{channel:e,isTerminal:n=>s.has(n)}}function Z(c,e,t){return c.parentId===e?!0:t===void 0?!1:c.meta?.correlationId===t}function ee(c,e){try{return structuredClone(e)}catch(t){throw new Error(`[yoltra] Initial state for slice "${String(c)}" 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 O(c,e){return process.env.NODE_ENV==="production"?c:k(c,new WeakSet,e)}const z=100,te=64,A=16,ne=3e4,se=16,$=Object.freeze({committed:!1,written:!1}),re=Object.freeze({committed:!0,written:!1}),ie=Object.freeze({committed:!0,written:!0}),j=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now();class P{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,"writtenEventSubscribers",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,"currentEvent",null);p(this,"transitionsThisDrain",0);p(this,"maxReduceDepth");p(this,"maxTransitionsPerDrain");p(this,"onCascade");p(this,"onRejected");p(this,"instrumentObservers",new Set);p(this,"changedPathSink",null);p(this,"stagingSink",null);p(this,"stagedRejection",null);p(this,"stagedRejectedBy","");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 B,this.connectorBus=new H,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.maxReduceDepth=e.maxReduceDepth??te,this.maxTransitionsPerDrain=e.maxTransitionsPerDrain??1/0,this.onCascade=e.onCascade,this.onRejected=e.onRejected,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.__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.warnedPayloadAliases.clear(),this.listeners.clear(),this.committedEventSubscribers.clear(),this.uncommittedEventSubscribers.clear(),this.writtenEventSubscribers.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 r=JSON.stringify(s);return`${n}::${r}`}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,r]of this.processedEvents)r<s&&this.processedEvents.delete(n);this.processedEvents.size===0&&this.eventCleanupTimer!==null&&(clearInterval(this.eventCleanupTimer),this.eventCleanupTimer=null)}reportCascade(e,t,s,n,r){console.error(`[yoltra] Cascade stopped: "${s.channel}/${s.type}" would exceed ${e} (${t}). This event was refused and the chain ends here. A chain this long is almost always two consumers emitting into each other — check what reacts to "${s.channel}/${s.type}" and what that emits in turn.`+(r.length>0?` Recent causal chain: ${r.join(" → ")} → (refused).`:""));try{this.onCascade?.({limit:e,limitValue:t,event:s,depth:n,chain:r})}catch(o){console.error("onCascade handler error:",o)}}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=this.scopedEmit(e),s=`${String(e.channel)}::${String(e.type)}`,n=this.effects.get(s);if(n&&n.size>0)for(const r of[...n])try{await r(e,this.getState,t)}catch(o){console.error("Effect error:",o),this.onEffectError?.(o,e)}for(const{effect:r,when:o}of this.patternEffects)if(this.matchesWhen(o,e))try{await r(e,this.getState,t)}catch(d){console.error("Effect error:",d),this.onEffectError?.(d,e)}}scopedEmit(e){const t={id:e.id,depth:e.depth??0,chain:[...this.currentEvent?.chain??[],e.id].slice(-A)};return((s,n,r,o)=>this.emitCaused(t,s,n,r,o))}notifyEventSubscribers(e,t){const s=`${String(e.channel)}::${String(e.type)}`,r=(t==="committed"?this.committedEventSubscribers:t==="written"?this.writtenEventSubscribers:this.uncommittedEventSubscribers).get(s);if(r?.size)for(const d of[...r])this.invokeEventSubscriber(d,e,t);if(t==="written")return;const o=this.allEventSubscribers.get(s);if(o?.size)for(const d of[...o])this.invokeEventSubscriber(d,e,t)}invokeEventSubscriber(e,t,s){try{const n=e(t,this.getState,this.emit,s);n&&typeof n.then=="function"&&n.catch(r=>console.error("Event subscription error:",r))}catch(n){console.error("Event subscription error:",n)}}stageSliceGuarded(e,t,s){try{return this.stageSlice(e,t,s)}catch(n){return console.error(`Reducer error in slice "${e}":`,n),this.onReducerError?.(n,t,e),null}}stageSlice(e,t,s){const n=this.state[e],r=this.reducers[e].reduce(n,t);if(F(r))return r;if(n===r)return null;const o=T(n,r);if(o.length===0)return null;const d=t.payload,i=process.env.NODE_ENV!=="production"&&d!==null&&typeof d=="object"?{watch:d,onFound:()=>{const a=`${e}:${t.channel}:${t.type}`;this.warnedPayloadAliases.has(a)||(this.warnedPayloadAliases.add(a),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;return s.push({name:e,prev:n,frozen:O(r,i),leafPaths:o}),null}commitStaged(e,t){if(e.length===0)return!1;const s={...this.state};for(const n of e)s[n.name]=n.frozen;if(this.state=s,this.changedPathSink)for(const n of e)for(const r of n.leafPaths)this.changedPathSink.push(r?`${n.name}.${r}`:n.name);for(const n of e){const r=new Set;for(const o of n.leafPaths){if(o===""){r.add("");continue}for(const d of P.buildAncestorPaths(o))r.add(d)}for(const o of r)this.connectorBus.emitWith(n.name,o,()=>({oldValue:this.getAtPath(n.prev,o),newValue:this.getAtPath(n.frozen,o),path:o,eventId:t.id,channel:t.channel,type:t.type}))}return!0}__devtoolsIntrospect(){const e=Object.keys(this.reducers).map(d=>{const i=this.patternReducers.get(d);return{name:d,when:i}}),t=[];for(const[d,i]of this.effects){if(i.size===0)continue;const[a,l]=d.split("::");for(const u of i){const f=this.effectMeta.get(u);t.push({channel:a,type:l,name:f?.name,description:f?.description})}}for(const d of this.patternEffects){const i=this.effectMeta.get(d.effect);t.push({channel:"*",type:"*",name:i?.name,description:i?.description})}const s=[];for(const d of this.middleware)typeof d=="function"?s.push({name:d.name||void 0}):s.push({name:d.meta?.name,description:d.meta?.description,when:d.when});const n=[];for(const d of this.connectorBus.__introspect())for(let i=0;i<d.count;i++)n.push({reducer:d.channel,property:d.type});const r=[];for(const[d,i]of this.committedEventSubscribers){if(i.size===0)continue;const[a,l]=d.split("::");for(let u=0;u<i.size;u++)r.push({channel:a,type:l,phase:"committed"})}for(const[d,i]of this.uncommittedEventSubscribers){if(i.size===0)continue;const[a,l]=d.split("::");for(let u=0;u<i.size;u++)r.push({channel:a,type:l,phase:"uncommitted"})}for(const[d,i]of this.allEventSubscribers){if(i.size===0)continue;const[a,l]=d.split("::");for(let u=0;u<i.size;u++)r.push({channel:a,type:l,phase:"all"})}const o=this.listeners.size;return{reducers:e,effects:t,middleware:s,atomic:n,event:r,coarse:o,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 r=!1;Object.keys(this.reducers).forEach(o=>{const d=t?.[o],i=s?.[o];if(i===void 0){process.env.NODE_ENV!=="production"&&console.warn(`[yoltra] External state is missing slice "${String(o)}"; retaining its current value. Time-travel snapshots should contain all slices.`);return}if(d===i)return;const a=O(i);n[o]=a,r=!0;const l=T(d,i);if(l.length===0)return;const u=new Set;for(const f of l){if(f===""){u.add("");continue}for(const m of P.buildAncestorPaths(f))u.add(m)}for(const f of u){const m=this.getAtPath(d,f),h=this.getAtPath(a,f);this.connectorBus.emit(o,f,{oldValue:m,newValue:h,path:f})}}),r&&(this.state=n),r&&this.listeners.forEach(o=>o())}__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,r=[];this.stagingSink=r;let o=null;try{this.reducerBus.emit(n.channel,n.type,n.payload,n),o=this.stagedRejection;for(const[i,a]of this.patternReducers){if(o!==null)break;if(this.matchesWhen(a,n)){const l=this.stageSliceGuarded(i,n,r);l!==null&&(o=l)}}}finally{this.stagingSink=null,this.stagedRejection=null,this.stagedRejectedBy=""}const d=o===null&&this.commitStaged(r,n);this.notifyEventSubscribers(n,"committed"),d&&(this.notifyEventSubscribers(n,"written"),this.listeners.forEach(i=>i()))}}async emit(e,t,s,n){return this.emitCaused(null,e,t,s,n)}async emitCaused(e,t,s,n,r){const o=r?.dedupKey,d=this.dedupConfig.windowMs;if(r?.skipDedup!==!0&&(d>0||o!==void 0)){const m=o!==void 0&&d<=0?z:d,h=o!==void 0?`${t}::${s}::#${o}`:this.fingerprint(t,s,n);if(this.shouldDedupe(h,m))return $}const i=r?.id??this.idFactory(),a=this.currentEvent??e,l=a===null?0:a.depth+1;if(a!==null&&l>this.maxReduceDepth)return this.reportCascade("maxReduceDepth",this.maxReduceDepth,{channel:t,type:s,payload:n,id:i,...r?.meta!==void 0?{meta:r.meta}:{},parentId:a.id,depth:l},l,a.chain),$;let u;const f=new Promise(m=>{u=m});return this.reduceQueue.push({channel:t,type:s,payload:n,id:i,meta:r?.meta,resolve:u,...a!==null?{parentId:a.id,depth:l,chain:a.chain}:{}}),this.drainReduce(),f}drainReduce(){if(!this.isReducing){this.isReducing=!0,this.transitionsThisDrain=0;try{for(;this.reduceQueue.length>0;){const e=this.reduceQueue.shift(),{channel:t,type:s,payload:n,id:r,meta:o,resolve:d,parentId:i,depth:a,chain:l}=e,u={channel:t,type:s,payload:n,id:r,...o!==void 0?{meta:o}:{},...i!==void 0?{parentId:i,depth:a}:{}};if(i!==void 0&&++this.transitionsThisDrain>this.maxTransitionsPerDrain){this.reportCascade("maxTransitionsPerDrain",this.maxTransitionsPerDrain,u,a,l),d($);continue}this.currentEvent={id:r,depth:a??0,chain:[...l??[],r].slice(-A)};const f=this.instrumentObservers.size>0,m=f?this.state:void 0,h=f?[]:void 0;h!==void 0&&(this.changedPathSink=h);const y=f?j():0;let g=$;try{g=this.applyEventSync(u)}catch(E){console.error("Emit reduce error:",E)}finally{f&&(this.changedPathSink=null),this.currentEvent=null}f&&this.emitInstrumentation(u,g,h??[],m,j()-y),this.runEventEffects(u,g,d)}}finally{this.isReducing=!1}}}applyEventSync(e){for(const o of this.middleware){const d=this.getMiddlewareWhen(o);if(!this.matchesWhen(d,e))continue;const i=this.getMiddlewareFunction(o);let a;try{a=i(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(l){console.error("Middleware error:",l),a=!1}if(!a)return this.notifyEventSubscribers(e,"uncommitted"),$}const t=[];this.stagingSink=t;let s=null,n="";try{this.reducerBus.emit(e.channel,e.type,e.payload,e),s=this.stagedRejection,n=this.stagedRejectedBy;for(const[o,d]of this.patternReducers){if(s!==null)break;if(this.matchesWhen(d,e)){const i=this.stageSliceGuarded(o,e,t);i!==null&&(s=i,n=o)}}}finally{this.stagingSink=null,this.stagedRejection=null,this.stagedRejectedBy=""}if(s!==null)return this.onRejected?.(s,e,n),this.notifyEventSubscribers(e,"committed"),{committed:!0,written:!1,rejected:s};const r=this.commitStaged(t,e);return this.notifyEventSubscribers(e,"committed"),r&&(this.notifyEventSubscribers(e,"written"),this.listeners.forEach(o=>o())),r?ie:re}async runEventEffects(e,t,s){this.inFlightEffects++;try{t.committed&&await this.notifyEffects(e)}catch(n){console.error("Effect error:",n)}finally{this.inFlightEffects--,s(t)}}instrument(e){return this.instrumentObservers.add(e),()=>{this.instrumentObservers.delete(e)}}emitInstrumentation(e,t,s,n,r){const o={},d={};for(const a of s)o[a]=this.getAtPath(n,a),d[a]=this.getAtPath(this.state,a);const i={event:{id:e.id,channel:e.channel,type:e.type,payload:e.payload,...e.meta!==void 0?{meta:e.meta}:{}},committed:t.committed,changedPaths:s,prevValues:o,nextValues:d,reduceTimeMs:r,...t.rejected!==void 0?{rejected:t.rejected}:{}};for(const a of[...this.instrumentObservers])try{a(i)}catch(l){console.error("Instrumentation observer error:",l)}}connect(e,t,s){const n=this.connectorBus.on(e.reducer,e.property,t);if(s?.immediate===!0){const r=this.state[e.reducer],o=e.property.includes("*")?"":e.property;t({oldValue:void 0,newValue:this.getAtPath(r,o),path:o})}return n}onEvent(e,t,s,n="committed"){const r=`${e}::${String(t)}`,o=n==="committed"?this.committedEventSubscribers:n==="uncommitted"?this.uncommittedEventSubscribers:n==="written"?this.writtenEventSubscribers:this.allEventSubscribers;return o.has(r)||o.set(r,new Set),o.get(r).add(s),()=>{const d=o.get(r);d&&(d.delete(s),d.size===0&&o.delete(r))}}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(Object.prototype.hasOwnProperty.call(this.reducers,e))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())}}call(e,t,s,n){const{channel:r,isTerminal:o}=X(n.reply),d=n.timeoutMs??ne,i=new Y(n.highWaterMark??se),a=this.idFactory();let l,u,f=!1;const m=new Promise((b,S)=>{l=b,u=S});m.catch(()=>{});let h=null,y=null;const g=(b,S=!1)=>{f||(f=!0,h!==null&&clearTimeout(h),h=null,y?.(),y=null,S?i.end():i.close(),n.signal?.removeEventListener("abort",E),b())};function E(){g(()=>u(new I(String(n.signal?.reason??"signal aborted"))))}const M=()=>{h!==null&&clearTimeout(h),h=setTimeout(()=>{g(()=>u(new U(e,t,d)))},d),h.unref?.()};return y=this.registerEffect({when:{channel:r},effect:async b=>{if(!f&&Z(b,a,n.correlationId)){if(M(),o(String(b.type))){g(()=>l(b),!0);return}await i.put(b)}}}),n.signal!==void 0&&(n.signal.aborted?E():n.signal.addEventListener("abort",E,{once:!0})),M(),this.emit(e,t,s,{id:a,...n.correlationId!==void 0?{meta:{correlationId:n.correlationId}}:{}}),{then:(b,S)=>m.then(b,S),catch:b=>m.catch(b),finally:b=>m.finally(b),get dropped(){return i.droppedCount},cancel:(b="cancelled")=>{g(()=>u(new I(b)))},[Symbol.asyncIterator]:()=>(i.beginConsuming(),{next:()=>i.take(),return:async()=>(i.close(),{value:void 0,done:!0})})}}registerEffect(e){const{effect:t,meta:s,when:n}=e,r=[];if(s&&this.effectMeta.set(t,s),n&&("any"in n&&n.any===!0||"channel"in n||"channels"in n)){const i={effect:t,when:n};return this.patternEffects.add(i),()=>{this.patternEffects.delete(i)}}const d=this.normalizeEventKeys(e);if(d.length===0&&!n){const i={effect:t,when:{any:!0}};return this.patternEffects.add(i),()=>{this.patternEffects.delete(i)}}for(const[i,a]of d){const l=`${String(i)}::${String(a)}`;this.effects.has(l)||this.effects.set(l,new Set),this.effects.get(l).add(t),r.push(()=>{const u=this.effects.get(l);u&&(u.delete(t),u.size===0&&this.effects.delete(l))})}return()=>{for(const i of r)i()}}onEffect(e,t,s){const n=async(r,o,d)=>{if(r.channel!==e||r.type!==t)return;const i=r;return s(i.payload,o,d,i)};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)),r=Object.entries(e),o=new Set(r.map(([d])=>d));for(const d of n)o.has(d)||this.unmountSlice(d,{deleteState:!0});for(const[d,i]of r)n.has(d)?(this.unmountSlice(d,{deleteState:!1}),this.mountSlice(d,i,{preserveState:s})):this.mountSlice(d,i,{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:r,state:o,when:d}=t;if(this.reducers[e]=new W(r),(!s.preserveState||this.state[n]===void 0)&&(this.state={...this.state,[n]:O(ee(n,o))}),d&&("any"in d&&d.any===!0||"channel"in d||"channels"in d)){this.patternReducers.set(e,d),this.sliceUnsubs.set(n,[]);return}const a=this.normalizeEventKeys(t);if(a.length===0&&!d){this.patternReducers.set(e,{any:!0}),this.sliceUnsubs.set(n,[]);return}const l=[];for(const[u,f]of a){const m=this.reducerBus.on(u,f,(h,y)=>{const g=y??{channel:u,type:f,payload:h,id:this.idFactory()};if(this.stagingSink===null)return;const E=this.stageSliceGuarded(e,g,this.stagingSink);E!==null&&this.stagedRejection===null&&(this.stagedRejection=E,this.stagedRejectedBy=e)});l.push(m)}this.sliceUnsubs.set(n,l)}unmountSlice(e,t){const s=e;this.patternReducers.delete(e);const n=this.sliceUnsubs.get(s);if(n){for(const r of n)try{r()}catch(o){console.error(`[Store error]: ${o}`)}this.sliceUnsubs.delete(s)}if(delete this.reducers[e],t.deleteState){const{[s]:r,...o}=this.state;this.state=o}}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 r=e;for(const o of n){if(r==null)return;r=r[o]}return r}static buildAncestorPaths(e){if(!e)return[];const s=(e[0]==="."?e.slice(1):e).split("."),n=[];for(let r=0;r<s.length;r++)n.push(s.slice(0,r+1).join("."));return n}}function oe(c){return new P({...c,reducer:c.reducer??{},middleware:c.middleware??[],effects:c.effects??[]})}const ce=c=>(e,t)=>t.map(s=>[e,s]),ae=()=>c=>c,_=new Set;function de(c){const e=String(c);_.has(e)||(_.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 le(c,e){if(c.length!==e.length)return e;for(let t=0;t<c.length;t++)if(c[t]!==e[t])return e;return c}function ue(c={}){const e=c.selectId??(i=>i.id),{sortComparer:t}=c,s=(i,a)=>{if(t===void 0)return a;const l=[...a].sort((u,f)=>{const m=i.entities[u],h=i.entities[f];return m===void 0||h===void 0?0:t(m,h)});return le(a,l)},n=(i,a,l)=>{const u={...i,entities:a,ids:l};return{...u,ids:s(u,l)}},r=(i,a,l)=>{let u=null,f=null;for(const m of a){const h=e(m);process.env.NODE_ENV!=="production"&&String(h).includes(".")&&de(h);const y=(u??i.entities)[h];if(y!==void 0&&l==="add")continue;const g=y!==void 0&&l==="upsert"?{...y,...m}:m;u??(u={...i.entities}),u[h]=g,y===void 0&&(f??(f=[...i.ids]),f.push(h))}return u===null?i:n(i,u,f??i.ids)},o=(i,a)=>{let l=null;for(const{id:u,changes:f}of a){const m=(l??i.entities)[u];m!==void 0&&(l??(l={...i.entities}),l[u]={...m,...f})}return l===null?i:n(i,l,i.ids)},d=(i,a)=>{const l=new Set(a.filter(f=>i.entities[f]!==void 0));if(l.size===0)return i;const u={...i.entities};for(const f of l)delete u[f];return n(i,u,i.ids.filter(f=>!l.has(f)))};return{getInitialState(i){const a={ids:[],entities:{}};return i===void 0?a:{...a,...i}},addOne:(i,a)=>r(i,[a],"add"),addMany:(i,a)=>r(i,a,"add"),setOne:(i,a)=>r(i,[a],"set"),setMany:(i,a)=>r(i,a,"set"),setAll:(i,a)=>{const l={},u=[];for(const f of a){const m=e(f);l[m]===void 0&&u.push(m),l[m]=f}return n(i,l,u)},updateOne:(i,a)=>o(i,[a]),updateMany:(i,a)=>o(i,a),upsertOne:(i,a)=>r(i,[a],"upsert"),upsertMany:(i,a)=>r(i,a,"upsert"),removeOne:(i,a)=>d(i,[a]),removeMany:(i,a)=>d(i,a),removeAll:i=>i.ids.length===0?i:n(i,{},[]),selectIds:i=>i.ids,selectEntities:i=>i.entities,selectAll:i=>i.ids.map(a=>i.entities[a]),selectById:(i,a)=>i.entities[a],selectTotal:i=>i.ids.length,idsPath:"ids",pathTo:(i,a)=>a===void 0?`entities.${i}`:`entities.${i}.${a}`,anyField:i=>`entities.*.${i}`}}const w="$yoltra";function C(c,e={}){const t=e.maxNodes??1e5,s=e.sanitize,n=[],r=new Map;let o=0,d=!1;function i(l,u){if(s!==void 0&&(l=s(u,l)),o+=1,o>t)return d=!0,{[w]:"unsupported",kind:"truncated"};switch(typeof l){case"undefined":return{[w]:"undefined"};case"bigint":return{[w]:"bigint",value:l.toString()};case"number":return Number.isNaN(l)?{[w]:"nan"}:l===1/0?{[w]:"infinity",sign:1}:l===-1/0?{[w]:"infinity",sign:-1}:l;case"function":case"symbol":return n.push(u),{[w]:"unsupported",kind:typeof l};case"string":case"boolean":return l}if(l===null)return null;const f=l,m=r.get(f);if(m!==void 0)return{[w]:"ref",path:m};if(r.set(f,u),l instanceof Date)return{[w]:"date",iso:l.toISOString()};if(l instanceof RegExp)return{[w]:"regexp",source:l.source,flags:l.flags};if(l instanceof Error)return{[w]:"error",name:l.name,message:l.message};if(l instanceof Map){const y=[];let g=0;for(const[E,M]of l)y.push([i(E,`${u}/@k${g}`),i(M,`${u}/${g}`)]),g+=1;return{[w]:"map",entries:y}}if(l instanceof Set){const y=[];let g=0;for(const E of l)y.push(i(E,`${u}/${g}`)),g+=1;return{[w]:"set",values:y}}if(Array.isArray(l))return l.map((y,g)=>i(y,`${u}/${g}`));const h={};for(const[y,g]of Object.entries(l))h[y]=i(g,`${u}/${V(y)}`);return w in h?{[w]:"escaped",value:h}:h}return{value:i(c,""),report:{truncated:d,unsupported:n}}}function L(c){const e=new Map,t=[];function s(o,d){if(o===null||typeof o!="object")return o;if(Array.isArray(o)){const a=[];return e.set(d,a),o.forEach((l,u)=>{if(N(l)){t.push({target:a,key:u,path:l.path}),a[u]=void 0;return}a[u]=s(l,`${d}/${u}`)}),a}if(typeof o[w]=="string"){const a=o;switch(a[w]){case"undefined":return;case"nan":return Number.NaN;case"infinity":return a.sign===1?1/0:-1/0;case"bigint":return BigInt(a.value);case"date":return new Date(a.iso);case"regexp":return new RegExp(a.source,a.flags);case"error":{const l=new Error(a.message);return l.name=a.name,l}case"unsupported":return;case"ref":return;case"map":{const l=new Map;return e.set(d,l),a.entries.forEach(([u,f],m)=>{l.set(s(u,`${d}/@k${m}`),s(f,`${d}/${m}`))}),l}case"set":{const l=new Set;return e.set(d,l),a.values.forEach((u,f)=>l.add(s(u,`${d}/${f}`))),l}case"escaped":return n(a.value,d);default:return}}return n(o,d)}function n(o,d){const i={};e.set(d,i);for(const[a,l]of Object.entries(o)){const u=`${d}/${V(a)}`;if(N(l)){t.push({target:i,key:a,path:l.path}),i[a]=void 0;continue}i[a]=s(l,u)}return i}const r=s(c,"");e.set("",r);for(const{target:o,key:d,path:i}of t)o[d]=e.get(i);return r}function N(c){return c!==null&&typeof c=="object"&&c[w]==="ref"&&typeof c.path=="string"}function V(c){return c.replace(/~/g,"~0").replace(/\//g,"~1")}function fe(c,e,t={}){let s=t.maxNodes??1e5;for(let n=0;n<8;n+=1){const{value:r,report:o}=C(c,{...t,maxNodes:s});let d;try{d=JSON.stringify(r)?.length??0}catch{d=Number.POSITIVE_INFINITY}if(d<=e)return o.truncated?{value:r,truncated:!0,note:`State was too large to send in full; parts beyond ${s} nodes are omitted.`}:{value:r,truncated:!1};const i=Math.floor(s*e*.8/d);if(s=Math.max(1,Math.min(i,s-1)),s<=1&&n>0)break}return{value:{[w]:"unsupported",kind:"truncated"},truncated:!0,note:`State exceeds the ${e}-byte transport limit and could not be reduced to fit.`}}function v(c,e,t){c.onError?.(e,t)}async function he(c){const e={slices:{},restored:!1};let t;try{t=c.source??await c.adapter.read(c.key)}catch(n){return v(c,n,"read"),e}if(t==null||t==="")return e;let s;try{s=L(JSON.parse(t))}catch(n){return v(c,n,"decode"),e}if(s===null||typeof s!="object"||typeof s.version!="number")return v(c,new Error("persisted payload is not a recognisable envelope"),"decode"),e;if(s.version!==c.version){if(c.migrate===void 0)return v(c,new Error(`persisted state is version ${s.version}, this build expects ${c.version}, and no migrate was supplied`),"migrate"),e;try{const n=c.migrate(s.slices,s.version);return n===null?e:{slices:n,restored:!0}}catch(n){return v(c,n,"migrate"),e}}return{slices:s.slices??{},restored:!0}}function pe(c,e){if(!e.restored)return c;const t={};for(const[s,n]of Object.entries(c)){const r=e.slices[s];t[s]=r===void 0?n:{...n,state:r}}return t}function Q(c,e){const t=c??{},s=e.slices===void 0?t:Object.fromEntries(e.slices.filter(n=>n in t).map(n=>[n,t[n]]));return JSON.stringify(C({version:e.version,slices:s}).value)}function me(c,e){const t=e.throttleMs??250,s=e.slices;let n=null,r=!1;const o=()=>{if(r){r=!1;try{const a=e.adapter.write(e.key,Q(c.getState(),e));a instanceof Promise&&a.catch(l=>v(e,l,"write"))}catch(a){v(e,a,"write")}}},d=()=>{if(r=!0,t<=0){o();return}n===null&&(n=setTimeout(()=>{n=null,o()},t),n.unref?.())},i=c.instrument(a=>{if(s===void 0){d();return}(a.changedPaths??[]).some(u=>s.some(f=>u===f||u.startsWith(`${f}.`)))&&d()});return()=>{i(),n!==null&&(clearTimeout(n),n=null),o()}}function ye(c,e){return Q(c.getState(),e)}function ge(c){return{read:e=>c.getItem(e),write:(e,t)=>c.setItem(e,t),remove:e=>c.removeItem(e)}}function Ee(c){const e=new Map(Object.entries(c??{}));return{read:t=>e.get(t)??null,write:(t,s)=>{e.set(t,s)},remove:t=>{e.delete(t)}}}exports.CallAbortedError=I;exports.CallTimeoutError=U;exports.EventBus=B;exports.LooseEventBus=H;exports.Reducer=W;exports.Rejected=q;exports.Store=P;exports.createEntityAdapter=ue;exports.createMemoryAdapter=Ee;exports.createStore=oe;exports.createWebStorageAdapter=ge;exports.decodeState=L;exports.dehydrate=ye;exports.detectChangedProps=T;exports.encodeState=C;exports.encodeStateBounded=fe;exports.eventKeys=ae;exports.freezeState=k;exports.hydrate=he;exports.isRejected=F;exports.persist=me;exports.typedEvents=ce;exports.withHydration=pe;
11
11
  //# sourceMappingURL=yoltra.cjs.map