@yoltra/core 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -87,6 +87,63 @@ store.connect({ reducer: "todos", property: "items.**" }, (change) =>
87
87
  );
88
88
  ```
89
89
 
90
+ ### Slices that hold a single value
91
+
92
+ A slice does not have to be an object. A primitive, a `Map`, a `Set` or a `Date` is a valid
93
+ slice state, and it commits like any other:
94
+
95
+ ```typescript
96
+ const store = createStore({
97
+ name: "session",
98
+ reducer: {
99
+ token: {
100
+ state: null as string | null,
101
+ when: { keys: [["auth", "login"]] },
102
+ reducer: (_state, event) => event.payload.token,
103
+ },
104
+ },
105
+ });
106
+
107
+ await store.emit("auth", "login", { token: "abc123" });
108
+ store.getState().token; // "abc123"
109
+ ```
110
+
111
+ Such a slice has no property beneath it, so its changes are reported at the **slice root** —
112
+ the empty path. Subscribe to it with `property: ""`:
113
+
114
+ ```typescript
115
+ store.connect({ reducer: "token", property: "" }, (change) =>
116
+ console.log("token:", change.oldValue, " --> ", change.newValue),
117
+ );
118
+ ```
119
+
120
+ The types know the difference. `property` on a root-value slice accepts `""` and nothing else —
121
+ there is no key to address — and the value comes back correctly typed:
122
+
123
+ ```typescript
124
+ const token = useAtomicProp({ reducer: "token", property: "" }); // string | null
125
+ ```
126
+
127
+ ### `""` versus `"**"` — watching a whole slice
128
+
129
+ Two subscriptions sound alike and are not:
130
+
131
+ | Pattern | Fires when |
132
+ |---|---|
133
+ | `""` | the slice's **whole value** is replaced — a primitive changes, a `Map` is rebuilt, an object slice becomes `null` |
134
+ | `"**"` | **anything** in the slice changes, at any depth. Matches the root too, since `**` matches zero segments |
135
+ | `"*"` | one level down, exactly. Never matches the root |
136
+
137
+ **`"**"` is the whole-slice subscription, and it works for every slice regardless of shape.**
138
+ Reach for `""` only when you mean the root value itself; on an object slice it stays quiet,
139
+ because such a slice reports its changes at their leaves.
140
+
141
+ `Map` and `Set` are compared by reference, not by entry: a reducer returning a new `Map` is a
142
+ change, mutating one in place is not. That follows from the immutability contract rather than
143
+ being a special case — build a new collection instead of mutating the stored one. It is also why
144
+ they have no paths beneath them: `"byId"` is subscribable, `"byId.get"` is not, and the types
145
+ say so.
146
+
90
147
  ### Immutability
91
148
 
92
149
  State is deep-frozen before committing. Mutations throw in strict mode:
@@ -1,4 +1,4 @@
1
- import { Event, EventMapBase } from '../types';
1
+ import { Event, EventMapBase } from '../types.js';
2
2
  /**
3
3
  * Minimal, synchronous pub/sub event bus keyed by **channel** and **type**.
4
4
  *
@@ -1,2 +1,2 @@
1
- export * from './EventBus';
2
- export * from './LooseEventBus';
1
+ export * from './EventBus.js';
2
+ export * from './LooseEventBus.js';
@@ -5,19 +5,19 @@
5
5
  *
6
6
  * @packageDocumentation
7
7
  */
8
- export { EventBus } from './eventBus/EventBus';
9
- export { LooseEventBus } from './eventBus/LooseEventBus';
10
- export { Reducer } from './reducer/Reducer';
11
- export { Store, createStore, typedEvents } from './store/Store';
12
- export { detectChangedProps } from './utils/detectChangedProps';
13
- export { freezeState } from './utils/immutability';
14
- export { eventKeys } from './types';
15
- export type { EventMapBase, EventKey, Event, EventUnion, Change, Emit, EmitOptions, EventMeta, InstrumentedEvent, InstrumentationObserver, Unsubscribe, StoreSpec, StoreInstance, ReducerSpec, ReducerFunction, ReducersMapAny, StateFromReducers, EMFromReducersStrict, EffectSpec, EffectFunction, MiddlewareFunction, MiddlewareSpec, MiddlewareInput, DeepReadonly, DeepRO, Primitive, Path, PathValue, WithGlob, Dotted, EventPhase, EventSubscriptionHandler, NarrowedEventHandler, When, EventFromWhen, EventConsumerType, EventConsumerMeta, } from './types';
16
- export { createEntityAdapter } from './entity/entityAdapter';
17
- export type { EntityAdapter, EntityAdapterOptions, EntityId, EntityState, EntityUpdate, } from './entity/entityAdapter';
18
- export { decodeState, encodeState, encodeStateBounded } from './serialize/codec';
19
- export type { BoundedEncodeResult, EncodeOptions, EncodeReport, EncodeResult, } from './serialize/codec';
20
- export { dehydrate, hydrate, persist, withHydration } from './persistence/persist';
21
- export type { Hydration, PersistableStore, PersistenceAdapter, PersistencePhase, PersistOptions, } from './persistence/persist';
22
- export { createMemoryAdapter, createWebStorageAdapter } from './persistence/adapters';
23
- export type { WebStorageLike } from './persistence/adapters';
8
+ export { EventBus } from './eventBus/EventBus.js';
9
+ export { LooseEventBus } from './eventBus/LooseEventBus.js';
10
+ export { Reducer } from './reducer/Reducer.js';
11
+ export { Store, createStore, typedEvents } from './store/Store.js';
12
+ export { detectChangedProps } from './utils/detectChangedProps.js';
13
+ export { freezeState } from './utils/immutability.js';
14
+ export { eventKeys } from './types.js';
15
+ export type { EventMapBase, EventKey, Event, EventUnion, Change, Emit, EmitOptions, EventMeta, InstrumentedEvent, InstrumentationObserver, Unsubscribe, StoreSpec, StoreInstance, ReducerSpec, ReducerFunction, ReducersMapAny, StateFromReducers, EMFromReducersStrict, EffectSpec, EffectFunction, MiddlewareFunction, MiddlewareSpec, MiddlewareInput, DeepReadonly, DeepRO, Primitive, RootValue, Path, PathValue, WithGlob, Dotted, EventPhase, EventSubscriptionHandler, NarrowedEventHandler, When, EventFromWhen, EventConsumerType, EventConsumerMeta, } from './types.js';
16
+ export { createEntityAdapter } from './entity/entityAdapter.js';
17
+ export type { EntityAdapter, EntityAdapterOptions, EntityId, EntityState, EntityUpdate, } from './entity/entityAdapter.js';
18
+ export { decodeState, encodeState, encodeStateBounded } from './serialize/codec.js';
19
+ export type { BoundedEncodeResult, EncodeOptions, EncodeReport, EncodeResult, } from './serialize/codec.js';
20
+ export { dehydrate, hydrate, persist, withHydration } from './persistence/persist.js';
21
+ export type { Hydration, PersistableStore, PersistenceAdapter, PersistencePhase, PersistOptions, } from './persistence/persist.js';
22
+ export { createMemoryAdapter, createWebStorageAdapter } from './persistence/adapters.js';
23
+ export type { WebStorageLike } from './persistence/adapters.js';
@@ -1,4 +1,4 @@
1
- import { PersistenceAdapter } from './persist';
1
+ import { PersistenceAdapter } from './persist.js';
2
2
  /** The slice of the Web Storage API used here. */
3
3
  export interface WebStorageLike {
4
4
  getItem(key: string): string | null;
@@ -1,4 +1,4 @@
1
- import { EventMapBase, EventUnion, ReducerFunction } from '../types';
1
+ import { EventMapBase, EventUnion, ReducerFunction } from '../types.js';
2
2
  /**
3
3
  * Thin wrapper around a pure reducer function (stateful event consumer):
4
4
  * given a state `S` and an event (from {@link EventUnion | `EventUnion<EM>`}),
@@ -1,4 +1,4 @@
1
- import { Event, EventMapBase, EventKey, EventUnion, Change, DeepReadonly, EffectSpec, EventMeta, MiddlewareInput, ReducersMapAny, ReducerSpec, StateFromReducers, StoreInstance, StoreSpec, Unsubscribe, EMFromReducersStrict, Emit, EmitOptions, InstrumentationObserver, EventPhase, NarrowedEventHandler, When } from '../types';
1
+ import { Event, EventMapBase, EventKey, EventUnion, Change, DeepReadonly, EffectSpec, EventMeta, MiddlewareInput, ReducersMapAny, ReducerSpec, StateFromReducers, StoreInstance, StoreSpec, Unsubscribe, EMFromReducersStrict, Emit, EmitOptions, InstrumentationObserver, EventPhase, NarrowedEventHandler, When } from '../types.js';
2
2
  export declare class Store<EM extends EventMapBase, R extends string, S extends Record<R, any>> implements StoreInstance<R, S, EM> {
3
3
  /**
4
4
  * Store name (used by DevTools & diagnostics).
@@ -338,6 +338,11 @@ export declare class Store<EM extends EventMapBase, R extends string, S extends
338
338
  * For each changed **leaf path** (via {@link detectChangedProps}), emits that leaf and
339
339
  * all of its **ancestors** once (e.g., `"data"`, `"data.123"`, `"data.123.title"`).
340
340
  *
341
+ * A slice whose state **is** a single value — a primitive, a `Map`/`Set`, a `Date` — has no
342
+ * leaf below its root, and `detectChangedProps` reports its change as the empty path `""`.
343
+ * That path is emitted as-is, so `connect({ reducer, property: "" })` (and any `**` pattern)
344
+ * hears it. It has no ancestors to walk.
345
+ *
341
346
  * **State Immutability**: When a slice changes, a new state object is created via
342
347
  * shallow spread: `{ ...this.state, [sliceName]: newSlice }`. This ensures that
343
348
  * `this.state` reference changes, enabling efficient change detection via `===`.
@@ -994,9 +994,14 @@ export type EventFromWhen<EM extends EventMapBase, W extends When<EM>> = W exten
994
994
  * type T3 = PathValue<S, 'todos'>; // Array<{ title: string; done: boolean }>
995
995
  * ```
996
996
  *
997
+ * @remarks
998
+ * The empty path resolves to `T` itself, matching what the code has always done: both the
999
+ * store's internal path reader and the React one return the object unchanged for `""`. The type
1000
+ * used to say `never`, so a subscription to a root-value slice was typed as nothing at all.
1001
+ *
997
1002
  * @public
998
1003
  */
999
- export type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : K extends `${number}` ? T extends readonly (infer E)[] ? PathValue<E, Rest> : never : never : P extends keyof T ? T[P] : P extends `${number}` ? T extends readonly (infer E)[] ? E : never : never;
1004
+ export type PathValue<T, P extends string> = P extends "" ? T : P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : K extends `${number}` ? T extends readonly (infer E)[] ? PathValue<E, Rest> : never : never : P extends keyof T ? T[P] : P extends `${number}` ? T extends readonly (infer E)[] ? E : never : never;
1000
1005
  /**
1001
1006
  * Type discriminator for event consumers.
1002
1007
  *
@@ -1045,6 +1050,23 @@ export type DeepRO<T> = DeepReadonly<T>;
1045
1050
  * @public
1046
1051
  */
1047
1052
  export type Primitive = string | number | boolean | bigint | symbol | null | undefined | Date | RegExp;
1053
+ /**
1054
+ * A value with **no addressable interior**: its changes are reported at the slice root rather
1055
+ * than at a path beneath it.
1056
+ *
1057
+ * @remarks
1058
+ * The distinction the path types were missing. `Map` and `Set` keep their contents outside own
1059
+ * enumerable keys, so walking them with `keyof` yields the names of their *methods* — which is
1060
+ * how `"byId.get"` and `"byId.size"` came to be offered as subscribable paths, and why a slice
1061
+ * holding a plain number autocompleted `"toFixed"`. Neither ever notified anything, because
1062
+ * `detectChangedProps` reports such a value at its own path and never descends into it.
1063
+ *
1064
+ * This is the type-level counterpart of that runtime rule: what the diff reports at the root,
1065
+ * the types address at the root, with the empty path.
1066
+ *
1067
+ * @public
1068
+ */
1069
+ export type RootValue = Primitive | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>;
1048
1070
  /**
1049
1071
  * Compute dotted paths of T, including nested objects and arrays.
1050
1072
  *
@@ -1052,7 +1074,7 @@ export type Primitive = string | number | boolean | bigint | symbol | null | und
1052
1074
  *
1053
1075
  * @public
1054
1076
  */
1055
- export type Path<T> = T extends Primitive ? never : T extends readonly (infer U)[] ? `${number}` | (Path<U> extends never ? never : `${number}.${Path<U>}`) : {
1077
+ export type Path<T> = T extends RootValue ? never : T extends readonly (infer U)[] ? `${number}` | (Path<U> extends never ? never : `${number}.${Path<U>}`) : {
1056
1078
  [K in keyof T & string]: T[K] extends Primitive ? K : K | (Path<T[K]> extends never ? never : `${K}.${Path<T[K]>}`);
1057
1079
  }[keyof T & string];
1058
1080
  /**
@@ -1068,9 +1090,19 @@ export type WithGlob<T extends string> = T | `${string}*${string}`;
1068
1090
  *
1069
1091
  * @typeParam Slice - Slice state type.
1070
1092
  *
1093
+ * @remarks
1094
+ * A slice that **is** one value — a primitive, a `Map`, a `Set`, a `Date` — has no key to
1095
+ * address, and its only subscribable path is the empty one. Saying so is what makes
1096
+ * `{ reducer, property: "" }` type-check where it can actually fire, instead of falling through
1097
+ * to the untyped `property: string` overload and returning `unknown`.
1098
+ *
1099
+ * The conditional distributes over unions, which is why a nullable object slice gets both:
1100
+ * `Dotted<{ a: number } | null>` is `"" | "a"`. That is exactly right — such a slice really does
1101
+ * change at its root when it becomes `null`, and at `"a"` otherwise.
1102
+ *
1071
1103
  * @public
1072
1104
  */
1073
- export type Dotted<Slice> = (keyof Slice & string) | Path<Slice>;
1105
+ export type Dotted<Slice> = Slice extends RootValue ? "" : (keyof Slice & string) | Path<Slice>;
1074
1106
  /**
1075
1107
  * Deep readonly type: recursively makes all properties readonly.
1076
1108
  *
@@ -61,6 +61,12 @@
61
61
  *
62
62
  * @remarks
63
63
  * - If `oldState === newState` (same reference), returns `[]` immediately.
64
+ * - A change at the **root** — the values themselves differ and neither is a walkable object,
65
+ * as for a primitive, a `Map`/`Set`, or two `Date`s — is reported at the `path` given, which
66
+ * is `""` for the default root call. `[""]` therefore means *"the whole value changed"*, and
67
+ * is emphatically **not** the same as `[]`. Callers must not filter it out for falsiness:
68
+ * doing so is indistinguishable from "nothing changed", which is how a store slice holding a
69
+ * primitive once silently refused every update it was given.
64
70
  * - For objects, only **own enumerable** keys are compared (via `Object.keys`).
65
71
  * - Returned paths are **leaf paths** where a primitive/terminal difference was detected; for arrays,
66
72
  * a length change is treated as a leaf change at the array path.
@@ -1,4 +1,4 @@
1
- import { DeepReadonly } from '../types';
1
+ import { DeepReadonly } from '../types.js';
2
2
  /**
3
3
  * Deep-freezes a value **in place** and returns it as {@link DeepReadonly | `DeepReadonly<T>`}.
4
4
  *
@@ -1,2 +1,2 @@
1
- export * from './detectChangedProps';
2
- export * from './immutability';
1
+ export * from './detectChangedProps.js';
2
+ export * from './immutability.js';
@@ -0,0 +1,11 @@
1
+ /*!
2
+ * @yoltra/core v0.5.0
3
+ * (c) 2026 Manu Ramirez <@pixerael>
4
+ * License: MIT
5
+ * Homepage: https://yoltra.dev
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree
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;
11
+ //# sourceMappingURL=yoltra.cjs.map