@yoltra/core 0.6.0 → 0.7.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/dist/yoltra.mjs CHANGED
@@ -1,23 +1,13 @@
1
1
  /*!
2
- * @yoltra/core v0.6.0
2
+ * @yoltra/core v0.7.0
3
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
- var K = Object.defineProperty;
11
- var F = (c, e, t) => e in c ? K(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
12
- var p = (c, e, t) => F(c, typeof e != "symbol" ? e + "" : e, t);
13
- class U {
14
- constructor() {
15
- /**
16
- * Internal registry: `channel → type → Set<handler>`.
17
- * @internal
18
- */
19
- p(this, "handlers", /* @__PURE__ */ new Map());
20
- }
4
+ * License: MIT */
5
+ class W {
6
+ /**
7
+ * Internal registry: `channel → type → Set<handler>`.
8
+ * @internal
9
+ */
10
+ handlers = /* @__PURE__ */ new Map();
21
11
  /**
22
12
  * Subscribes a handler to an exact `(channel, type)`.
23
13
  *
@@ -107,9 +97,9 @@ class U {
107
97
  emit(e, t, s, n) {
108
98
  const r = this.handlers.get(e);
109
99
  if (!r) return;
110
- const o = r.get(t);
111
- if (!(!o || o.size === 0))
112
- for (const l of [...o])
100
+ const c = r.get(t);
101
+ if (!(!c || c.size === 0))
102
+ for (const l of [...c])
113
103
  try {
114
104
  l(s, n);
115
105
  } catch (i) {
@@ -133,37 +123,35 @@ class U {
133
123
  this.handlers.clear();
134
124
  }
135
125
  }
136
- class L {
137
- constructor() {
138
- /**
139
- * Exact handlers: `channel → type → [handlers]`.
140
- * @internal
141
- */
142
- p(this, "handlers", /* @__PURE__ */ new Map());
143
- /**
144
- * Pattern handlers with `*` and `**`: `channel → pattern(string) → [handlers]`.
145
- * @internal
146
- */
147
- p(this, "patternHandlers", /* @__PURE__ */ new Map());
148
- /**
149
- * Patterns bucketed by their first segment, so an emit tests only what could match.
150
- *
151
- * @remarks
152
- * Delivery used to walk every pattern registered on the channel and run the full segment
153
- * matcher against each. That is linear in the number of patterns rather than in the number
154
- * that match, and it re-split both the pattern and the subject on every test — for a thousand
155
- * patterns, two thousand string splits to deliver one event.
156
- *
157
- * A subject's first segment can only be matched by a pattern whose first segment is that same
158
- * literal, or is `*` or `**`. Bucketing on that turns the common shape — distinct event
159
- * families like `panel.*` and `order.**` — from a scan of everything into a map lookup plus
160
- * the handful that begin with a wildcard.
161
- *
162
- * It buys nothing for a channel where every pattern starts with `**`, since all of those must
163
- * still be tested. That is the honest worst case, and it is unchanged rather than worsened.
164
- */
165
- p(this, "patternIndex", /* @__PURE__ */ new Map());
166
- }
126
+ class U {
127
+ /**
128
+ * Exact handlers: `channel → type → [handlers]`.
129
+ * @internal
130
+ */
131
+ handlers = /* @__PURE__ */ new Map();
132
+ /**
133
+ * Pattern handlers with `*` and `**`: `channel → pattern(string) → [handlers]`.
134
+ * @internal
135
+ */
136
+ patternHandlers = /* @__PURE__ */ new Map();
137
+ /**
138
+ * Patterns bucketed by their first segment, so an emit tests only what could match.
139
+ *
140
+ * @remarks
141
+ * Delivery used to walk every pattern registered on the channel and run the full segment
142
+ * matcher against each. That is linear in the number of patterns rather than in the number
143
+ * that match, and it re-split both the pattern and the subject on every test — for a thousand
144
+ * patterns, two thousand string splits to deliver one event.
145
+ *
146
+ * A subject's first segment can only be matched by a pattern whose first segment is that same
147
+ * literal, or is `*` or `**`. Bucketing on that turns the common shape — distinct event
148
+ * families like `panel.*` and `order.**` — from a scan of everything into a map lookup plus
149
+ * the handful that begin with a wildcard.
150
+ *
151
+ * It buys nothing for a channel where every pattern starts with `**`, since all of those must
152
+ * still be tested. That is the honest worst case, and it is unchanged rather than worsened.
153
+ */
154
+ patternIndex = /* @__PURE__ */ new Map();
167
155
  /**
168
156
  * Subscribes a handler to either an **exact** type or a **pattern**.
169
157
  *
@@ -201,13 +189,13 @@ class L {
201
189
  if (this.isPattern(n)) {
202
190
  const r = n;
203
191
  this.patternHandlers.has(e) || this.patternHandlers.set(e, /* @__PURE__ */ new Map());
204
- const o = this.patternHandlers.get(e);
205
- return o.has(r) || (o.set(r, []), this.indexPattern(e, r)), o.get(r).push(s), () => this.offPattern(e, r, s);
192
+ const c = this.patternHandlers.get(e);
193
+ return c.has(r) || (c.set(r, []), this.indexPattern(e, r)), c.get(r).push(s), () => this.offPattern(e, r, s);
206
194
  } else {
207
195
  const r = this.normalizeTypeKey(n);
208
196
  this.handlers.has(e) || this.handlers.set(e, /* @__PURE__ */ new Map());
209
- const o = this.handlers.get(e);
210
- return o.has(r) || o.set(r, []), o.get(r).push(s), () => this.offExactNormalized(e, r, s);
197
+ const c = this.handlers.get(e);
198
+ return c.has(r) || c.set(r, []), c.get(r).push(s), () => this.offExactNormalized(e, r, s);
211
199
  }
212
200
  }
213
201
  /**
@@ -245,8 +233,8 @@ class L {
245
233
  if (!n) return;
246
234
  const r = n.get(t);
247
235
  if (!r) return;
248
- const o = r.indexOf(s);
249
- o !== -1 && r.splice(o, 1), r.length === 0 && n.delete(t), n.size === 0 && this.handlers.delete(e);
236
+ const c = r.indexOf(s);
237
+ c !== -1 && r.splice(c, 1), r.length === 0 && n.delete(t), n.size === 0 && this.handlers.delete(e);
250
238
  }
251
239
  /**
252
240
  * Internal removal for a **pattern** subscription. No-ops if missing.
@@ -261,8 +249,8 @@ class L {
261
249
  if (!n) return;
262
250
  const r = n.get(t);
263
251
  if (!r) return;
264
- const o = r.indexOf(s);
265
- 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));
252
+ const c = r.indexOf(s);
253
+ c !== -1 && r.splice(c, 1), r.length === 0 && (n.delete(t), this.unindexPattern(e, t)), n.size === 0 && (this.patternHandlers.delete(e), this.patternIndex.delete(e));
266
254
  }
267
255
  /**
268
256
  * Emits an event to all exact subscribers first, then to **matching pattern** subscribers.
@@ -285,20 +273,20 @@ class L {
285
273
  * @public
286
274
  */
287
275
  emit(e, t, s) {
288
- const n = String(t), r = this.normalizeTypeKey(n), o = this.handlers.get(e)?.get(r) ?? [], l = this.matchingPatternHandlers(e, n), i = /* @__PURE__ */ new Set(), a = (d) => {
289
- for (const u of [...d])
290
- if (!i.has(u)) {
291
- i.add(u);
276
+ const n = String(t), r = this.normalizeTypeKey(n), c = this.handlers.get(e)?.get(r) ?? [], l = this.matchingPatternHandlers(e, n), i = /* @__PURE__ */ new Set(), a = (u) => {
277
+ for (const d of [...u])
278
+ if (!i.has(d)) {
279
+ i.add(d);
292
280
  try {
293
- u(s);
294
- } catch (f) {
295
- console.error(f);
281
+ d(s);
282
+ } catch (h) {
283
+ console.error(h);
296
284
  continue;
297
285
  }
298
286
  }
299
287
  };
300
- a(o);
301
- for (const d of l) a(d);
288
+ a(c);
289
+ for (const u of l) a(u);
302
290
  }
303
291
  /**
304
292
  * Emits a payload that is only built if somebody is listening.
@@ -317,22 +305,22 @@ class L {
317
305
  * @public
318
306
  */
319
307
  emitWith(e, t, s) {
320
- const n = String(t), r = this.normalizeTypeKey(n), o = this.handlers.get(e)?.get(r) ?? [], l = this.matchingPatternHandlers(e, n);
321
- if (o.length === 0 && l.length === 0) return;
322
- const i = s(), a = /* @__PURE__ */ new Set(), d = (u) => {
323
- for (const f of [...u])
324
- if (!a.has(f)) {
325
- a.add(f);
308
+ const n = String(t), r = this.normalizeTypeKey(n), c = this.handlers.get(e)?.get(r) ?? [], l = this.matchingPatternHandlers(e, n);
309
+ if (c.length === 0 && l.length === 0) return;
310
+ const i = s(), a = /* @__PURE__ */ new Set(), u = (d) => {
311
+ for (const h of [...d])
312
+ if (!a.has(h)) {
313
+ a.add(h);
326
314
  try {
327
- f(i);
328
- } catch (m) {
329
- console.error(m);
315
+ h(i);
316
+ } catch (p) {
317
+ console.error(p);
330
318
  continue;
331
319
  }
332
320
  }
333
321
  };
334
- d(o);
335
- for (const u of l) d(u);
322
+ u(c);
323
+ for (const d of l) u(d);
336
324
  }
337
325
  /**
338
326
  * Determines if a string is a **pattern** (contains `*`).
@@ -373,13 +361,13 @@ class L {
373
361
  indexPattern(e, t) {
374
362
  let s = this.patternIndex.get(e);
375
363
  s === void 0 && (s = { byHead: /* @__PURE__ */ new Map(), anyHead: [] }, this.patternIndex.set(e, s));
376
- const n = this.splitPath(t), r = { pattern: t, segments: n }, o = n[0];
377
- if (o === void 0 || o === "*" || o === "**") {
364
+ const n = this.splitPath(t), r = { pattern: t, segments: n }, c = n[0];
365
+ if (c === void 0 || c === "*" || c === "**") {
378
366
  s.anyHead.push(r);
379
367
  return;
380
368
  }
381
- const l = s.byHead.get(o);
382
- l === void 0 ? s.byHead.set(o, [r]) : l.push(r);
369
+ const l = s.byHead.get(c);
370
+ l === void 0 ? s.byHead.set(c, [r]) : l.push(r);
383
371
  }
384
372
  /**
385
373
  * Removes a pattern from the index. Paired with {@link LooseEventBus.offPattern}.
@@ -390,8 +378,8 @@ class L {
390
378
  if (s === void 0) return;
391
379
  const n = this.splitPath(t)[0], r = n === void 0 || n === "*" || n === "**" ? s.anyHead : s.byHead.get(n);
392
380
  if (r === void 0) return;
393
- const o = r.findIndex((l) => l.pattern === t);
394
- o !== -1 && r.splice(o, 1), r.length === 0 && r !== s.anyHead && n !== void 0 && s.byHead.delete(n);
381
+ const c = r.findIndex((l) => l.pattern === t);
382
+ c !== -1 && r.splice(c, 1), r.length === 0 && r !== s.anyHead && n !== void 0 && s.byHead.delete(n);
395
383
  }
396
384
  /**
397
385
  * The handler lists of every pattern matching this subject.
@@ -407,18 +395,18 @@ class L {
407
395
  matchingPatternHandlers(e, t) {
408
396
  const s = this.patternHandlers.get(e), n = this.patternIndex.get(e);
409
397
  if (s === void 0 || s.size === 0 || n === void 0) return [];
410
- const r = this.splitPath(t), o = [], l = (a) => {
411
- for (const d of a) {
412
- if (!this.matchSegments(d.segments, r)) continue;
413
- const u = s.get(d.pattern);
414
- u !== void 0 && o.push(u);
398
+ const r = this.splitPath(t), c = [], l = (a) => {
399
+ for (const u of a) {
400
+ if (!this.matchSegments(u.segments, r)) continue;
401
+ const d = s.get(u.pattern);
402
+ d !== void 0 && c.push(d);
415
403
  }
416
404
  }, i = r[0];
417
405
  if (i !== void 0) {
418
406
  const a = n.byHead.get(i);
419
407
  a !== void 0 && l(a);
420
408
  }
421
- return l(n.anyHead), o;
409
+ return l(n.anyHead), c;
422
410
  }
423
411
  /**
424
412
  * Pattern matcher over dot-separated segments, which arrive already split.
@@ -449,14 +437,14 @@ class L {
449
437
  * @internal
450
438
  */
451
439
  matchSegments(e, t) {
452
- let s = 0, n = 0, r = -1, o = 0;
440
+ let s = 0, n = 0, r = -1, c = 0;
453
441
  for (; n < t.length; )
454
442
  if (s < e.length && (e[s] === "*" || e[s] === t[n]))
455
443
  s++, n++;
456
444
  else if (s < e.length && e[s] === "**")
457
- r = s, o = n, s++;
445
+ r = s, c = n, s++;
458
446
  else if (r !== -1)
459
- s = r + 1, n = ++o;
447
+ s = r + 1, n = ++c;
460
448
  else
461
449
  return !1;
462
450
  for (; s < e.length && e[s] === "**"; ) s++;
@@ -494,7 +482,12 @@ class L {
494
482
  return e;
495
483
  }
496
484
  }
497
- class V {
485
+ class L {
486
+ /**
487
+ * The underlying pure reducer function.
488
+ * @internal
489
+ */
490
+ _reduce;
498
491
  /**
499
492
  * Creates a new {@link Reducer} from a pure reducer function.
500
493
  *
@@ -511,11 +504,6 @@ class V {
511
504
  * @public
512
505
  */
513
506
  constructor(e) {
514
- /**
515
- * The underlying pure reducer function.
516
- * @internal
517
- */
518
- p(this, "_reduce");
519
507
  this._reduce = e;
520
508
  }
521
509
  /**
@@ -537,137 +525,162 @@ class V {
537
525
  }
538
526
  }
539
527
  const T = /* @__PURE__ */ new Set();
540
- function O(c, e) {
541
- const t = c ? `${c}.${e}` : e;
528
+ function O(o, e) {
529
+ const t = o ? `${o}.${e}` : e;
542
530
  T.has(t) || (T.add(t), console.warn(
543
- `[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.`
531
+ `[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.`
544
532
  ));
545
533
  }
546
- function I(c, e, t = "", s = /* @__PURE__ */ new Map()) {
534
+ function I(o, e, t = "", s = /* @__PURE__ */ new Map()) {
547
535
  const n = [];
548
- return P(c, e, t, s, n), n;
536
+ return P(o, e, t, s, n), n;
549
537
  }
550
- function P(c, e, t, s, n) {
551
- if (c === e) return;
552
- if (typeof c != "object" || typeof e != "object" || c === null || e === null) {
553
- if (typeof c == "number" && Number.isNaN(c) && Number.isNaN(e))
538
+ function P(o, e, t, s, n) {
539
+ if (o === e) return;
540
+ if (typeof o != "object" || typeof e != "object" || o === null || e === null) {
541
+ if (typeof o == "number" && Number.isNaN(o) && Number.isNaN(e))
554
542
  return;
555
543
  n.push(t);
556
544
  return;
557
545
  }
558
- if (c instanceof Date && e instanceof Date) {
559
- c.getTime() !== e.getTime() && n.push(t);
546
+ if (o instanceof Date && e instanceof Date) {
547
+ o.getTime() !== e.getTime() && n.push(t);
560
548
  return;
561
549
  }
562
- if (c instanceof RegExp && e instanceof RegExp) {
563
- (c.source !== e.source || e.flags !== c.flags) && n.push(t);
550
+ if (o instanceof RegExp && e instanceof RegExp) {
551
+ (o.source !== e.source || e.flags !== o.flags) && n.push(t);
564
552
  return;
565
553
  }
566
- if (c instanceof Map || e instanceof Map) {
554
+ if (o instanceof Map || e instanceof Map) {
567
555
  n.push(t);
568
556
  return;
569
557
  }
570
- if (c instanceof Set || e instanceof Set) {
558
+ if (o instanceof Set || e instanceof Set) {
571
559
  n.push(t);
572
560
  return;
573
561
  }
574
- const r = c, o = e, l = s.get(r);
575
- if (l?.has(o)) return;
562
+ const r = o, c = e, l = s.get(r);
563
+ if (l?.has(c)) return;
576
564
  const i = l ?? /* @__PURE__ */ new Set();
577
- i.add(o), l || s.set(r, i);
565
+ i.add(c), l || s.set(r, i);
578
566
  try {
579
- const a = Array.isArray(c), d = Array.isArray(e);
580
- if (a !== d) {
567
+ const a = Array.isArray(o), u = Array.isArray(e);
568
+ if (a !== u) {
581
569
  n.push(t);
582
570
  return;
583
571
  }
584
572
  if (a) {
585
- const h = c, y = e;
586
- h.length !== y.length && t && n.push(t);
587
- const g = Math.min(h.length, y.length);
588
- for (let w = 0; w < g; w++)
589
- h[w] !== y[w] && P(h[w], y[w], t ? `${t}.${w}` : `${w}`, s, n);
590
- for (let w = g; w < Math.max(h.length, y.length); w++)
591
- n.push(t ? `${t}.${w}` : `${w}`);
573
+ const f = o, m = e;
574
+ f.length !== m.length && t && n.push(t);
575
+ const y = Math.min(f.length, m.length);
576
+ for (let g = 0; g < y; g++)
577
+ f[g] !== m[g] && P(f[g], m[g], t ? `${t}.${g}` : `${g}`, s, n);
578
+ for (let g = y; g < Math.max(f.length, m.length); g++)
579
+ n.push(t ? `${t}.${g}` : `${g}`);
592
580
  return;
593
581
  }
594
- const u = Object.keys(c), f = Object.keys(e);
595
- if (u.length === 0 && f.length === 0) {
582
+ const d = Object.keys(o), h = Object.keys(e);
583
+ if (d.length === 0 && h.length === 0) {
596
584
  n.push(t);
597
585
  return;
598
586
  }
599
- let m = u.length === f.length;
600
- if (m) {
601
- for (let h = 0; h < f.length; h++)
602
- if (!Object.prototype.hasOwnProperty.call(c, f[h])) {
603
- m = !1;
587
+ let p = d.length === h.length;
588
+ if (p) {
589
+ for (let f = 0; f < h.length; f++)
590
+ if (!Object.prototype.hasOwnProperty.call(o, h[f])) {
591
+ p = !1;
604
592
  break;
605
593
  }
606
594
  }
607
- if (m) {
608
- for (const h of f)
609
- c[h] !== e[h] && (process.env.NODE_ENV !== "production" && h.includes(".") && O(t, h), P(c[h], e[h], t ? `${t}.${h}` : h, s, n));
595
+ if (p) {
596
+ for (const f of h)
597
+ o[f] !== e[f] && (process.env.NODE_ENV !== "production" && f.includes(".") && O(t, f), P(o[f], e[f], t ? `${t}.${f}` : f, s, n));
610
598
  return;
611
599
  }
612
- for (const h of f) {
613
- const y = Object.prototype.hasOwnProperty.call(c, h);
614
- if (y && c[h] === e[h]) continue;
615
- process.env.NODE_ENV !== "production" && h.includes(".") && O(t, h);
616
- const g = t ? `${t}.${h}` : h;
617
- if (!y) {
618
- n.push(g);
600
+ for (const f of h) {
601
+ const m = Object.prototype.hasOwnProperty.call(o, f);
602
+ if (m && o[f] === e[f]) continue;
603
+ process.env.NODE_ENV !== "production" && f.includes(".") && O(t, f);
604
+ const y = t ? `${t}.${f}` : f;
605
+ if (!m) {
606
+ n.push(y);
619
607
  continue;
620
608
  }
621
- P(c[h], e[h], g, s, n);
609
+ P(o[f], e[f], y, s, n);
622
610
  }
623
- for (const h of u)
624
- Object.prototype.hasOwnProperty.call(e, h) || (process.env.NODE_ENV !== "production" && h.includes(".") && O(t, h), n.push(t ? `${t}.${h}` : h));
611
+ for (const f of d)
612
+ Object.prototype.hasOwnProperty.call(e, f) || (process.env.NODE_ENV !== "production" && f.includes(".") && O(t, f), n.push(t ? `${t}.${f}` : f));
625
613
  } finally {
626
- i.delete(o), i.size === 0 && s.delete(r);
614
+ i.delete(c), i.size === 0 && s.delete(r);
627
615
  }
628
616
  }
629
- function M(c, e = /* @__PURE__ */ new WeakSet(), t) {
630
- if (c === null || typeof c != "object" || e.has(c) || (t !== void 0 && c === t.watch && t.onFound(), Object.isFrozen(c))) return c;
631
- if (e.add(c), Array.isArray(c)) {
632
- const s = c;
617
+ function M(o, e = /* @__PURE__ */ new WeakSet(), t) {
618
+ if (o === null || typeof o != "object" || e.has(o) || (t !== void 0 && o === t.watch && t.onFound(), Object.isFrozen(o))) return o;
619
+ if (e.add(o), Array.isArray(o)) {
620
+ const s = o;
633
621
  for (let n = 0; n < s.length; n++)
634
622
  s[n] = M(s[n], e, t);
635
623
  return Object.freeze(s);
636
624
  }
637
- for (const s of Object.getOwnPropertyNames(c)) {
638
- const n = Object.getOwnPropertyDescriptor(c, s);
639
- !n || !("value" in n) || (c[s] = M(c[s], e, t));
625
+ for (const s of Object.getOwnPropertyNames(o)) {
626
+ const n = Object.getOwnPropertyDescriptor(o, s);
627
+ !n || !("value" in n) || (o[s] = M(o[s], e, t));
640
628
  }
641
- for (const s of Object.getOwnPropertySymbols(c)) {
642
- const n = Object.getOwnPropertyDescriptor(c, s);
643
- !n || !("value" in n) || (c[s] = M(c[s], e, t));
629
+ for (const s of Object.getOwnPropertySymbols(o)) {
630
+ const n = Object.getOwnPropertyDescriptor(o, s);
631
+ !n || !("value" in n) || (o[s] = M(o[s], e, t));
632
+ }
633
+ return Object.freeze(o);
634
+ }
635
+ const B = /* @__PURE__ */ Symbol.for("yoltra.rejected");
636
+ function fe(o) {
637
+ return { [B]: !0, reason: o };
638
+ }
639
+ function V(o) {
640
+ return typeof o == "object" && o !== null && o[B] === !0;
641
+ }
642
+ class Q extends Error {
643
+ channel;
644
+ type;
645
+ idleMs;
646
+ constructor(e, t, s) {
647
+ super(
648
+ `[yoltra] call to "${e}/${t}" saw no correlated reply for ${s}ms. The timeout is idle rather than total, so this means the responder went quiet, not that it was slow. Check that something handles "${e}/${t}" 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.`
649
+ ), this.name = "CallTimeoutError", this.channel = e, this.type = t, this.idleMs = s;
650
+ }
651
+ }
652
+ class C extends Error {
653
+ constructor(e) {
654
+ super(`[yoltra] call aborted: ${e}`), this.name = "CallAbortedError";
644
655
  }
645
- return Object.freeze(c);
646
656
  }
647
- const N = /* @__PURE__ */ Symbol.for("yoltra.rejected");
648
- function le(c) {
649
- return { [N]: !0, reason: c };
657
+ function G(o) {
658
+ const [e, t] = o;
659
+ if (t === void 0) return { channel: e, isTerminal: () => !0 };
660
+ if (typeof t == "string") return { channel: e, isTerminal: (n) => n === t };
661
+ const s = new Set(t);
662
+ return { channel: e, isTerminal: (n) => s.has(n) };
650
663
  }
651
- function Q(c) {
652
- return typeof c == "object" && c !== null && c[N] === !0;
664
+ function J(o, e, t) {
665
+ return o.parentId === e ? !0 : t === void 0 ? !1 : o.meta?.correlationId === t;
653
666
  }
654
- class G {
667
+ class q {
655
668
  constructor(e) {
656
- p(this, "highWaterMark");
657
- p(this, "buffer", []);
658
- /** Consumers parked in `take`, oldest first. */
659
- p(this, "takers", []);
660
- /** Producers parked in `put`, each with the item they are waiting to hand over. */
661
- p(this, "putters", []);
662
- p(this, "consuming", !1);
663
- /** No more items will be accepted, but what is already here is still owed to the consumer. */
664
- p(this, "ended", !1);
665
- /** Abandoned: nothing further is owed to anybody. */
666
- p(this, "closed", !1);
667
- /** Items discarded because nobody was iterating and the buffer was full. */
668
- p(this, "dropped", 0);
669
669
  this.highWaterMark = e;
670
670
  }
671
+ highWaterMark;
672
+ buffer = [];
673
+ /** Consumers parked in `take`, oldest first. */
674
+ takers = [];
675
+ /** Producers parked in `put`, each with the item they are waiting to hand over. */
676
+ putters = [];
677
+ consuming = !1;
678
+ /** No more items will be accepted, but what is already here is still owed to the consumer. */
679
+ ended = !1;
680
+ /** Abandoned: nothing further is owed to anybody. */
681
+ closed = !1;
682
+ /** Items discarded because nobody was iterating and the buffer was full. */
683
+ dropped = 0;
671
684
  /** How many items were discarded for want of a consumer. */
672
685
  get droppedCount() {
673
686
  return this.dropped;
@@ -748,46 +761,375 @@ class G {
748
761
  t.release(), t = this.putters.shift();
749
762
  }
750
763
  }
751
- class J extends Error {
752
- constructor(t, s, n) {
753
- super(
754
- `[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.`
755
- );
756
- p(this, "channel");
757
- p(this, "type");
758
- p(this, "idleMs");
759
- this.name = "CallTimeoutError", this.channel = t, this.type = s, this.idleMs = n;
764
+ const Y = 3e4, X = 16;
765
+ function Z(o, e, t, s, n) {
766
+ const { channel: r, isTerminal: c } = G(n.reply), l = n.timeoutMs ?? Y, i = new q(n.highWaterMark ?? X), a = o.idFactory();
767
+ let u, d, h = !1;
768
+ const p = new Promise((E, v) => {
769
+ u = E, d = v;
770
+ });
771
+ p.catch(() => {
772
+ });
773
+ let f = null, m = null;
774
+ const y = (E, v = !1) => {
775
+ h || (h = !0, f !== null && clearTimeout(f), f = null, m?.(), m = null, v ? i.end() : i.close(), n.signal?.removeEventListener("abort", g), E());
776
+ };
777
+ function g() {
778
+ y(() => d(new C(String(n.signal?.reason ?? "signal aborted"))));
760
779
  }
780
+ const $ = () => {
781
+ f !== null && clearTimeout(f), f = setTimeout(() => {
782
+ y(() => d(new Q(e, t, l)));
783
+ }, l), f.unref?.();
784
+ };
785
+ return m = o.registerEffect({
786
+ // A pattern effect on the reply channel: which types are terminal is known, which are
787
+ // progress is not, so the filter cannot be a key list.
788
+ when: { channel: r },
789
+ effect: async (E) => {
790
+ if (!h && J(E, a, n.correlationId)) {
791
+ if ($(), c(String(E.type))) {
792
+ y(() => u(E), !0);
793
+ return;
794
+ }
795
+ await i.put(E);
796
+ }
797
+ }
798
+ }), n.signal !== void 0 && (n.signal.aborted ? g() : n.signal.addEventListener("abort", g, { once: !0 })), $(), o.emit(e, t, s, {
799
+ id: a,
800
+ ...n.correlationId !== void 0 ? { meta: { correlationId: n.correlationId } } : {}
801
+ }), {
802
+ then: (E, v) => p.then(E, v),
803
+ catch: (E) => p.catch(E),
804
+ finally: (E) => p.finally(E),
805
+ get dropped() {
806
+ return i.droppedCount;
807
+ },
808
+ cancel: (E = "cancelled") => {
809
+ y(() => d(new C(E)));
810
+ },
811
+ [Symbol.asyncIterator]: () => (i.beginConsuming(), {
812
+ next: () => i.take(),
813
+ // Called by `for await` on `break`, `return` or a throw. Without it, abandoning the
814
+ // loop would leave the effect registered and the producer parked for good.
815
+ return: async () => (i.close(), { value: void 0, done: !0 })
816
+ })
817
+ };
761
818
  }
762
- class C extends Error {
763
- constructor(e) {
764
- super(`[yoltra] call aborted: ${e}`), this.name = "CallAbortedError";
765
- }
819
+ function ee(o, e) {
820
+ if (!e) return o;
821
+ const s = (e[0] === "." ? e.slice(1) : e).split(".");
822
+ let n = o;
823
+ for (const r of s) {
824
+ if (n == null) return;
825
+ n = n[r];
826
+ }
827
+ return n;
766
828
  }
767
- function q(c) {
768
- const [e, t] = c;
769
- if (t === void 0) return { channel: e, isTerminal: () => !0 };
770
- if (typeof t == "string") return { channel: e, isTerminal: (n) => n === t };
771
- const s = new Set(t);
772
- return { channel: e, isTerminal: (n) => s.has(n) };
829
+ function te(o) {
830
+ if (!o) return [];
831
+ const t = (o[0] === "." ? o.slice(1) : o).split("."), s = [];
832
+ for (let n = 0; n < t.length; n++)
833
+ s.push(t.slice(0, n + 1).join("."));
834
+ return s;
773
835
  }
774
- function Y(c, e, t) {
775
- return c.parentId === e ? !0 : t === void 0 ? !1 : c.meta?.correlationId === t;
836
+ function k(o, e) {
837
+ return !o || "any" in o && o.any === !0 ? !0 : "keys" in o ? o.keys.some(
838
+ ([t, s]) => e.channel === t && e.type === s
839
+ ) : "channel" in o ? e.channel === o.channel : "channels" in o ? o.channels.includes(e.channel) : !1;
776
840
  }
777
- function X(c, e) {
841
+ function ne(o) {
842
+ return typeof o == "function" ? o : o.middleware;
843
+ }
844
+ function se(o) {
845
+ if (typeof o != "function")
846
+ return o.when;
847
+ }
848
+ function D(o) {
849
+ if (o.when) {
850
+ const e = o.when;
851
+ if ("keys" in e)
852
+ return e.keys;
853
+ }
854
+ return [];
855
+ }
856
+ function re(o, e) {
778
857
  try {
779
858
  return structuredClone(e);
780
859
  } catch (t) {
781
860
  throw new Error(
782
- `[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.`
861
+ `[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.`
783
862
  );
784
863
  }
785
864
  }
786
- function R(c, e) {
787
- return process.env.NODE_ENV === "production" ? c : M(c, /* @__PURE__ */ new WeakSet(), e);
865
+ function R(o, e) {
866
+ return process.env.NODE_ENV === "production" ? o : M(o, /* @__PURE__ */ new WeakSet(), e);
788
867
  }
789
- const D = 100, Z = 64, z = 16, ee = 3e4, te = 16, $ = Object.freeze({ committed: !1, written: !1 }), ne = Object.freeze({ committed: !0, written: !1 }), se = Object.freeze({ committed: !0, written: !0 }), A = () => typeof performance < "u" && typeof performance.now == "function" ? performance.now() : Date.now();
868
+ const A = 100, ie = 64, z = 16, S = Object.freeze({ committed: !1, written: !1 }), oe = Object.freeze({ committed: !0, written: !1 }), ce = Object.freeze({ committed: !0, written: !0 }), _ = () => typeof performance < "u" && typeof performance.now == "function" ? performance.now() : Date.now();
790
869
  class x {
870
+ /**
871
+ * Store name (used by DevTools & diagnostics).
872
+ *
873
+ * @public
874
+ */
875
+ name;
876
+ /**
877
+ * Registered middleware pipeline (run **before** reducers).
878
+ * Stores either raw functions (legacy) or MiddlewareSpec objects.
879
+ * Return `false` from the middleware function to stop propagation.
880
+ *
881
+ * @internal
882
+ */
883
+ middleware;
884
+ /**
885
+ * Installed slice reducers keyed by slice name.
886
+ *
887
+ * @internal
888
+ */
889
+ reducers;
890
+ /**
891
+ * Current immutable snapshot of the store state.
892
+ * This reference changes whenever any slice changes (shallow immutability).
893
+ *
894
+ * @internal
895
+ */
896
+ state;
897
+ /**
898
+ * Bus for reducer wiring (emit by `(channel, type)`).
899
+ *
900
+ * @internal
901
+ */
902
+ reducerBus;
903
+ /**
904
+ * Bus for **granular** connector events (emit by **dotted path** inside a slice).
905
+ *
906
+ * @internal
907
+ */
908
+ connectorBus;
909
+ /**
910
+ * Coarse-grained listeners (called once per committed event, only if state changed).
911
+ *
912
+ * @internal
913
+ */
914
+ listeners = /* @__PURE__ */ new Set();
915
+ /**
916
+ * Registered effect handlers keyed by `"channel::type"` for O(1) lookup.
917
+ * Used for effects with explicit `keys` targeting.
918
+ *
919
+ * @internal
920
+ */
921
+ effects = /* @__PURE__ */ new Map();
922
+ /**
923
+ * Pattern-based effects that need runtime matching.
924
+ * Used for effects with `when: { any }`, `{ channel }`, or `{ channels }`.
925
+ * Stores tuples of [effect function, when matcher].
926
+ *
927
+ * @internal
928
+ */
929
+ patternEffects = /* @__PURE__ */ new Set();
930
+ /**
931
+ * Committed event subscribers keyed by `"channel::type"` for O(1) lookup.
932
+ * Notified after reducers, before effects, for events that passed middleware.
933
+ *
934
+ * @internal
935
+ */
936
+ committedEventSubscribers = /* @__PURE__ */ new Map();
937
+ /**
938
+ * Uncommitted event subscribers keyed by `"channel::type"` for O(1) lookup.
939
+ * Notified when middleware rejects an event.
940
+ *
941
+ * @internal
942
+ */
943
+ uncommittedEventSubscribers = /* @__PURE__ */ new Map();
944
+ /**
945
+ * All-events subscribers keyed by `"channel::type"` for O(1) lookup.
946
+ * Notified for both committed and uncommitted events with phase parameter.
947
+ *
948
+ * @internal
949
+ */
950
+ /**
951
+ * Subscribers to events that actually changed state, notified after the commit.
952
+ *
953
+ * @remarks
954
+ * Separate from `committedEventSubscribers` rather than a filter over it, because the two
955
+ * answer different questions and one of them is load bearing: `committed` means "not vetoed"
956
+ * and fires for every event a store accepts, including every event in a store with no
957
+ * reducers. Narrowing it would have silently stopped toasts and analytics firing.
958
+ *
959
+ * @internal
960
+ */
961
+ writtenEventSubscribers = /* @__PURE__ */ new Map();
962
+ allEventSubscribers = /* @__PURE__ */ new Map();
963
+ /**
964
+ * Track reducerBus unsubs per slice for HMR/register/unregister.
965
+ *
966
+ * @internal
967
+ */
968
+ sliceUnsubs = /* @__PURE__ */ new Map();
969
+ /**
970
+ * Pattern-based reducers that need runtime matching.
971
+ * Used for reducers with `when: { any }`, `{ channel }`, or `{ channels }`.
972
+ * Maps slice name to the `when` matcher.
973
+ *
974
+ * @internal
975
+ */
976
+ patternReducers = /* @__PURE__ */ new Map();
977
+ /**
978
+ * Whether `__replayEvents()` is allowed.
979
+ * Set from `spec.devtools.allowReplay`.
980
+ *
981
+ * @internal
982
+ */
983
+ replayEnabled;
984
+ /**
985
+ * Produces the `id` for each emitted event. Defaults to `crypto.randomUUID()`; overridable
986
+ * via {@link StoreSpec.idFactory} for runtimes lacking it or for deterministic tests.
987
+ *
988
+ * @internal
989
+ */
990
+ idFactory;
991
+ /**
992
+ * Optional hook invoked when an effect throws/rejects. See
993
+ * {@link StoreSpec.onEffectError}. `await emit()` never rejects on effect
994
+ * failure — this is how callers observe effect errors.
995
+ */
996
+ onEffectError;
997
+ /**
998
+ * Optional hook invoked when a reducer throws. See {@link StoreSpec.onReducerError}. The
999
+ * failing slice is isolated rather than the event being rolled back, so this is the only
1000
+ * signal that a reducer misbehaved.
1001
+ */
1002
+ onReducerError;
1003
+ /**
1004
+ * `slice:channel:type` combinations already warned about for payload aliasing.
1005
+ *
1006
+ * @remarks
1007
+ * Development-only diagnostics have to stay quiet enough to be read. One warning names the
1008
+ * pattern; repeating it once per event would bury it.
1009
+ */
1010
+ warnedPayloadAliases = /* @__PURE__ */ new Set();
1011
+ /**
1012
+ * Pending events awaiting the **synchronous** reduce phase (middleware +
1013
+ * reducers + subscribers + coarse listeners). Drained by {@link drainReduce}.
1014
+ *
1015
+ * @internal
1016
+ */
1017
+ reduceQueue = [];
1018
+ /**
1019
+ * Re-entrancy guard for the synchronous reduce phase.
1020
+ *
1021
+ * @internal
1022
+ */
1023
+ isReducing = !1;
1024
+ /**
1025
+ * The event currently being reduced, or `null` outside the drain.
1026
+ *
1027
+ * @remarks
1028
+ * This is what makes causality exact rather than best-effort. The drain is synchronous — no
1029
+ * `await` can interleave — so any `emit` that arrives while it is set is, without ambiguity, a
1030
+ * consequence of this event. That catches the case a scoped `emit` closure cannot: a
1031
+ * middleware or subscriber that captured the store and calls `store.emit` directly instead of
1032
+ * using the injected one. Attribution should not depend on which reference a consumer reached
1033
+ * for.
1034
+ *
1035
+ * @internal
1036
+ */
1037
+ currentEvent = null;
1038
+ /**
1039
+ * Events processed by the drain currently in progress. Compared against
1040
+ * `maxTransitionsPerDrain`, which is off unless configured.
1041
+ *
1042
+ * @internal
1043
+ */
1044
+ transitionsThisDrain = 0;
1045
+ /**
1046
+ * Ceilings that stop a cascade from becoming a hung process. See {@link StoreSpec.maxReduceDepth}.
1047
+ *
1048
+ * @internal
1049
+ */
1050
+ maxReduceDepth;
1051
+ maxTransitionsPerDrain;
1052
+ onCascade;
1053
+ onRejected;
1054
+ /**
1055
+ * Registered instrumentation observers (DevTools seam). See {@link instrument}.
1056
+ *
1057
+ * @internal
1058
+ */
1059
+ instrumentObservers = /* @__PURE__ */ new Set();
1060
+ /**
1061
+ * Scratch array collecting slice-prefixed changed leaf paths during an
1062
+ * instrumented reduce. Set by {@link drainReduce} while observers are active;
1063
+ * appended to by {@link commitStaged}. `null` when not instrumenting.
1064
+ *
1065
+ * @internal
1066
+ */
1067
+ changedPathSink = null;
1068
+ /**
1069
+ * Where keyed reducers put their pending writes during a reduce, and the refusal one of them
1070
+ * returned.
1071
+ *
1072
+ * @remarks
1073
+ * Keyed reducers are invoked through `reducerBus`, which delivers to handlers and has no way
1074
+ * to hand a value back — the same reason `changedPathSink` exists. `null` outside a reduce.
1075
+ *
1076
+ * @internal
1077
+ */
1078
+ stagingSink = null;
1079
+ stagedRejection = null;
1080
+ stagedRejectedBy = "";
1081
+ /**
1082
+ * Count of effect tasks currently in flight; surfaced as queue depth by
1083
+ * {@link __devtoolsIntrospect}.
1084
+ *
1085
+ * @internal
1086
+ */
1087
+ inFlightEffects = 0;
1088
+ /**
1089
+ * Tracks processed events by fingerprint with timestamps for TTL-based deduplication.
1090
+ *
1091
+ * **Deduplication Behavior:**
1092
+ * - Events are fingerprinted using `channel::type::JSON(payload)`
1093
+ * - If an identical fingerprint is seen within the dedup window, it's skipped
1094
+ * - The window is 50ms in development, 100ms in production
1095
+ *
1096
+ * **Limitations:**
1097
+ * - Non-serializable payloads (functions, symbols, circular refs) get unique
1098
+ * fingerprints and won't be deduplicated
1099
+ * - Legitimate rapid-fire identical events may be incorrectly deduplicated
1100
+ * - The cache is bounded to 1000 entries with lazy pruning
1101
+ *
1102
+ * @internal
1103
+ */
1104
+ processedEvents = /* @__PURE__ */ new Map();
1105
+ /**
1106
+ * Lifetime count of events suppressed by the deduplication cache.
1107
+ * Exposed via {@link __devtoolsIntrospect} so the DevTools agent can
1108
+ * surface it in the STORE_METRICS response without further core changes.
1109
+ *
1110
+ * @internal
1111
+ */
1112
+ dedupCount = 0;
1113
+ /**
1114
+ * Store-owned metadata for registered effects, keyed by the effect function.
1115
+ * Kept **off** the caller's function object: mutating a user-owned function
1116
+ * (the old `fn.__quoMeta`) bled metadata across stores that share a handler
1117
+ * and left it attached after unregister. Cleared on {@link dispose}.
1118
+ *
1119
+ * @internal
1120
+ */
1121
+ effectMeta = /* @__PURE__ */ new WeakMap();
1122
+ /**
1123
+ * Configuration for event deduplication.
1124
+ * @internal
1125
+ */
1126
+ dedupConfig;
1127
+ /**
1128
+ * Timer for periodic cleanup of processed events.
1129
+ *
1130
+ * @internal
1131
+ */
1132
+ eventCleanupTimer = null;
791
1133
  /**
792
1134
  * Creates a store from a {@link StoreSpec}.
793
1135
  *
@@ -796,270 +1138,7 @@ class x {
796
1138
  * @public
797
1139
  */
798
1140
  constructor(e) {
799
- /**
800
- * Store name (used by DevTools & diagnostics).
801
- *
802
- * @public
803
- */
804
- p(this, "name");
805
- /**
806
- * Registered middleware pipeline (run **before** reducers).
807
- * Stores either raw functions (legacy) or MiddlewareSpec objects.
808
- * Return `false` from the middleware function to stop propagation.
809
- *
810
- * @internal
811
- */
812
- p(this, "middleware");
813
- /**
814
- * Installed slice reducers keyed by slice name.
815
- *
816
- * @internal
817
- */
818
- p(this, "reducers");
819
- /**
820
- * Current immutable snapshot of the store state.
821
- * This reference changes whenever any slice changes (shallow immutability).
822
- *
823
- * @internal
824
- */
825
- p(this, "state");
826
- /**
827
- * Bus for reducer wiring (emit by `(channel, type)`).
828
- *
829
- * @internal
830
- */
831
- p(this, "reducerBus");
832
- /**
833
- * Bus for **granular** connector events (emit by **dotted path** inside a slice).
834
- *
835
- * @internal
836
- */
837
- p(this, "connectorBus");
838
- /**
839
- * Coarse-grained listeners (called once per committed event, only if state changed).
840
- *
841
- * @internal
842
- */
843
- p(this, "listeners", /* @__PURE__ */ new Set());
844
- /**
845
- * Registered effect handlers keyed by `"channel::type"` for O(1) lookup.
846
- * Used for effects with explicit `keys` targeting.
847
- *
848
- * @internal
849
- */
850
- p(this, "effects", /* @__PURE__ */ new Map());
851
- /**
852
- * Pattern-based effects that need runtime matching.
853
- * Used for effects with `when: { any }`, `{ channel }`, or `{ channels }`.
854
- * Stores tuples of [effect function, when matcher].
855
- *
856
- * @internal
857
- */
858
- p(this, "patternEffects", /* @__PURE__ */ new Set());
859
- /**
860
- * Committed event subscribers keyed by `"channel::type"` for O(1) lookup.
861
- * Notified after reducers, before effects, for events that passed middleware.
862
- *
863
- * @internal
864
- */
865
- p(this, "committedEventSubscribers", /* @__PURE__ */ new Map());
866
- /**
867
- * Uncommitted event subscribers keyed by `"channel::type"` for O(1) lookup.
868
- * Notified when middleware rejects an event.
869
- *
870
- * @internal
871
- */
872
- p(this, "uncommittedEventSubscribers", /* @__PURE__ */ new Map());
873
- /**
874
- * All-events subscribers keyed by `"channel::type"` for O(1) lookup.
875
- * Notified for both committed and uncommitted events with phase parameter.
876
- *
877
- * @internal
878
- */
879
- /**
880
- * Subscribers to events that actually changed state, notified after the commit.
881
- *
882
- * @remarks
883
- * Separate from `committedEventSubscribers` rather than a filter over it, because the two
884
- * answer different questions and one of them is load bearing: `committed` means "not vetoed"
885
- * and fires for every event a store accepts, including every event in a store with no
886
- * reducers. Narrowing it would have silently stopped toasts and analytics firing.
887
- *
888
- * @internal
889
- */
890
- p(this, "writtenEventSubscribers", /* @__PURE__ */ new Map());
891
- p(this, "allEventSubscribers", /* @__PURE__ */ new Map());
892
- /**
893
- * Track reducerBus unsubs per slice for HMR/register/unregister.
894
- *
895
- * @internal
896
- */
897
- p(this, "sliceUnsubs", /* @__PURE__ */ new Map());
898
- /**
899
- * Pattern-based reducers that need runtime matching.
900
- * Used for reducers with `when: { any }`, `{ channel }`, or `{ channels }`.
901
- * Maps slice name to the `when` matcher.
902
- *
903
- * @internal
904
- */
905
- p(this, "patternReducers", /* @__PURE__ */ new Map());
906
- /**
907
- * Whether `__replayEvents()` is allowed.
908
- * Set from `spec.devtools.allowReplay`.
909
- *
910
- * @internal
911
- */
912
- p(this, "replayEnabled");
913
- /**
914
- * Produces the `id` for each emitted event. Defaults to `crypto.randomUUID()`; overridable
915
- * via {@link StoreSpec.idFactory} for runtimes lacking it or for deterministic tests.
916
- *
917
- * @internal
918
- */
919
- p(this, "idFactory");
920
- /**
921
- * Optional hook invoked when an effect throws/rejects. See
922
- * {@link StoreSpec.onEffectError}. `await emit()` never rejects on effect
923
- * failure — this is how callers observe effect errors.
924
- */
925
- p(this, "onEffectError");
926
- /**
927
- * Optional hook invoked when a reducer throws. See {@link StoreSpec.onReducerError}. The
928
- * failing slice is isolated rather than the event being rolled back, so this is the only
929
- * signal that a reducer misbehaved.
930
- */
931
- p(this, "onReducerError");
932
- /**
933
- * `slice:channel:type` combinations already warned about for payload aliasing.
934
- *
935
- * @remarks
936
- * Development-only diagnostics have to stay quiet enough to be read. One warning names the
937
- * pattern; repeating it once per event would bury it.
938
- */
939
- p(this, "warnedPayloadAliases", /* @__PURE__ */ new Set());
940
- /**
941
- * Pending events awaiting the **synchronous** reduce phase (middleware +
942
- * reducers + subscribers + coarse listeners). Drained by {@link drainReduce}.
943
- *
944
- * @internal
945
- */
946
- p(this, "reduceQueue", []);
947
- /**
948
- * Re-entrancy guard for the synchronous reduce phase.
949
- *
950
- * @internal
951
- */
952
- p(this, "isReducing", !1);
953
- /**
954
- * The event currently being reduced, or `null` outside the drain.
955
- *
956
- * @remarks
957
- * This is what makes causality exact rather than best-effort. The drain is synchronous — no
958
- * `await` can interleave — so any `emit` that arrives while it is set is, without ambiguity, a
959
- * consequence of this event. That catches the case a scoped `emit` closure cannot: a
960
- * middleware or subscriber that captured the store and calls `store.emit` directly instead of
961
- * using the injected one. Attribution should not depend on which reference a consumer reached
962
- * for.
963
- *
964
- * @internal
965
- */
966
- p(this, "currentEvent", null);
967
- /**
968
- * Events processed by the drain currently in progress. Compared against
969
- * `maxTransitionsPerDrain`, which is off unless configured.
970
- *
971
- * @internal
972
- */
973
- p(this, "transitionsThisDrain", 0);
974
- /**
975
- * Ceilings that stop a cascade from becoming a hung process. See {@link StoreSpec.maxReduceDepth}.
976
- *
977
- * @internal
978
- */
979
- p(this, "maxReduceDepth");
980
- p(this, "maxTransitionsPerDrain");
981
- p(this, "onCascade");
982
- p(this, "onRejected");
983
- /**
984
- * Registered instrumentation observers (DevTools seam). See {@link instrument}.
985
- *
986
- * @internal
987
- */
988
- p(this, "instrumentObservers", /* @__PURE__ */ new Set());
989
- /**
990
- * Scratch array collecting slice-prefixed changed leaf paths during an
991
- * instrumented reduce. Set by {@link drainReduce} while observers are active;
992
- * appended to by {@link commitStaged}. `null` when not instrumenting.
993
- *
994
- * @internal
995
- */
996
- p(this, "changedPathSink", null);
997
- /**
998
- * Where keyed reducers put their pending writes during a reduce, and the refusal one of them
999
- * returned.
1000
- *
1001
- * @remarks
1002
- * Keyed reducers are invoked through `reducerBus`, which delivers to handlers and has no way
1003
- * to hand a value back — the same reason `changedPathSink` exists. `null` outside a reduce.
1004
- *
1005
- * @internal
1006
- */
1007
- p(this, "stagingSink", null);
1008
- p(this, "stagedRejection", null);
1009
- p(this, "stagedRejectedBy", "");
1010
- /**
1011
- * Count of effect tasks currently in flight; surfaced as queue depth by
1012
- * {@link __devtoolsIntrospect}.
1013
- *
1014
- * @internal
1015
- */
1016
- p(this, "inFlightEffects", 0);
1017
- /**
1018
- * Tracks processed events by fingerprint with timestamps for TTL-based deduplication.
1019
- *
1020
- * **Deduplication Behavior:**
1021
- * - Events are fingerprinted using `channel::type::JSON(payload)`
1022
- * - If an identical fingerprint is seen within the dedup window, it's skipped
1023
- * - The window is 50ms in development, 100ms in production
1024
- *
1025
- * **Limitations:**
1026
- * - Non-serializable payloads (functions, symbols, circular refs) get unique
1027
- * fingerprints and won't be deduplicated
1028
- * - Legitimate rapid-fire identical events may be incorrectly deduplicated
1029
- * - The cache is bounded to 1000 entries with lazy pruning
1030
- *
1031
- * @internal
1032
- */
1033
- p(this, "processedEvents", /* @__PURE__ */ new Map());
1034
- /**
1035
- * Lifetime count of events suppressed by the deduplication cache.
1036
- * Exposed via {@link __devtoolsIntrospect} so the DevTools agent can
1037
- * surface it in the STORE_METRICS response without further core changes.
1038
- *
1039
- * @internal
1040
- */
1041
- p(this, "dedupCount", 0);
1042
- /**
1043
- * Store-owned metadata for registered effects, keyed by the effect function.
1044
- * Kept **off** the caller's function object: mutating a user-owned function
1045
- * (the old `fn.__quoMeta`) bled metadata across stores that share a handler
1046
- * and left it attached after unregister. Cleared on {@link dispose}.
1047
- *
1048
- * @internal
1049
- */
1050
- p(this, "effectMeta", /* @__PURE__ */ new WeakMap());
1051
- /**
1052
- * Configuration for event deduplication.
1053
- * @internal
1054
- */
1055
- p(this, "dedupConfig");
1056
- /**
1057
- * Timer for periodic cleanup of processed events.
1058
- *
1059
- * @internal
1060
- */
1061
- p(this, "eventCleanupTimer", null);
1062
- if (this.name = e.name ?? "yoltra Store", this.reducerBus = new U(), this.connectorBus = new L(), 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 ?? Z, this.maxTransitionsPerDrain = e.maxTransitionsPerDrain ?? 1 / 0, this.onCascade = e.onCascade, this.onRejected = e.onRejected, this.dedupConfig = {
1141
+ if (this.name = e.name ?? "yoltra Store", this.reducerBus = new W(), this.connectorBus = new U(), 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 ?? ie, this.maxTransitionsPerDrain = e.maxTransitionsPerDrain ?? 1 / 0, this.onCascade = e.onCascade, this.onRejected = e.onRejected, this.dedupConfig = {
1063
1142
  windowMs: e.dedupWindowMs ?? 0,
1064
1143
  maxCacheSize: 1e3
1065
1144
  }, Object.entries(e.reducer).forEach(([t, s]) => {
@@ -1142,7 +1221,7 @@ class x {
1142
1221
  * @internal
1143
1222
  */
1144
1223
  pruneProcessedEvents(e) {
1145
- const t = Math.max(this.dedupConfig.windowMs, D), s = e - t * 2;
1224
+ const t = Math.max(this.dedupConfig.windowMs, A), s = e - t * 2;
1146
1225
  for (const [n, r] of this.processedEvents)
1147
1226
  r < s && this.processedEvents.delete(n);
1148
1227
  this.processedEvents.size === 0 && this.eventCleanupTimer !== null && (clearInterval(this.eventCleanupTimer), this.eventCleanupTimer = null);
@@ -1164,55 +1243,10 @@ class x {
1164
1243
  );
1165
1244
  try {
1166
1245
  this.onCascade?.({ limit: e, limitValue: t, event: s, depth: n, chain: r });
1167
- } catch (o) {
1168
- console.error("onCascade handler error:", o);
1246
+ } catch (c) {
1247
+ console.error("onCascade handler error:", c);
1169
1248
  }
1170
1249
  }
1171
- /**
1172
- * Checks if an event matches a `When` matcher.
1173
- *
1174
- * @param when - The When matcher (or undefined for "all events").
1175
- * @param event - The event to check.
1176
- * @returns `true` if the event matches, `false` otherwise.
1177
- *
1178
- * @remarks
1179
- * - `undefined` or missing `when` matches ALL events.
1180
- * - `{ any: true }` matches ALL events.
1181
- * - `{ keys: [...] }` matches if event's `[channel, type]` is in the array.
1182
- * - `{ channel: 'x' }` matches if event's channel equals 'x'.
1183
- * - `{ channels: ['x', 'y'] }` matches if event's channel is in the array.
1184
- *
1185
- * @internal
1186
- */
1187
- matchesWhen(e, t) {
1188
- return !e || "any" in e && e.any === !0 ? !0 : "keys" in e ? e.keys.some(
1189
- ([s, n]) => t.channel === s && t.type === n
1190
- ) : "channel" in e ? t.channel === e.channel : "channels" in e ? e.channels.includes(t.channel) : !1;
1191
- }
1192
- /**
1193
- * Extracts the middleware function from a MiddlewareInput.
1194
- * Handles both raw functions (legacy) and MiddlewareSpec objects.
1195
- *
1196
- * @param input - MiddlewareInput (function or spec).
1197
- * @returns The middleware function.
1198
- *
1199
- * @internal
1200
- */
1201
- getMiddlewareFunction(e) {
1202
- return typeof e == "function" ? e : e.middleware;
1203
- }
1204
- /**
1205
- * Gets the `when` matcher from a MiddlewareInput.
1206
- *
1207
- * @param input - MiddlewareInput (function or spec).
1208
- * @returns The `when` matcher, or `undefined` for raw functions (match all).
1209
- *
1210
- * @internal
1211
- */
1212
- getMiddlewareWhen(e) {
1213
- if (typeof e != "function")
1214
- return e.when;
1215
- }
1216
1250
  /**
1217
1251
  * Invokes all registered **effects** for a given event.
1218
1252
  * Handles both key-based effects (O(1) lookup) and pattern-based effects (runtime matching).
@@ -1227,11 +1261,11 @@ class x {
1227
1261
  for (const r of [...n])
1228
1262
  try {
1229
1263
  await r(e, this.getState, t);
1230
- } catch (o) {
1231
- console.error("Effect error:", o), this.onEffectError?.(o, e);
1264
+ } catch (c) {
1265
+ console.error("Effect error:", c), this.onEffectError?.(c, e);
1232
1266
  }
1233
- for (const { effect: r, when: o } of this.patternEffects)
1234
- if (this.matchesWhen(o, e))
1267
+ for (const { effect: r, when: c } of this.patternEffects)
1268
+ if (k(c, e))
1235
1269
  try {
1236
1270
  await r(e, this.getState, t);
1237
1271
  } catch (l) {
@@ -1254,7 +1288,7 @@ class x {
1254
1288
  depth: e.depth ?? 0,
1255
1289
  chain: [...this.currentEvent?.chain ?? [], e.id].slice(-z)
1256
1290
  };
1257
- return ((s, n, r, o) => this.emitCaused(t, s, n, r, o));
1291
+ return ((s, n, r, c) => this.emitCaused(t, s, n, r, c));
1258
1292
  }
1259
1293
  /**
1260
1294
  * Notifies event subscribers for a specific phase.
@@ -1271,9 +1305,9 @@ class x {
1271
1305
  if (r?.size)
1272
1306
  for (const l of [...r]) this.invokeEventSubscriber(l, e, t);
1273
1307
  if (t === "written") return;
1274
- const o = this.allEventSubscribers.get(s);
1275
- if (o?.size)
1276
- for (const l of [...o]) this.invokeEventSubscriber(l, e, t);
1308
+ const c = this.allEventSubscribers.get(s);
1309
+ if (c?.size)
1310
+ for (const l of [...c]) this.invokeEventSubscriber(l, e, t);
1277
1311
  }
1278
1312
  /**
1279
1313
  * Invokes a single event-subscription handler **fire-and-forget**: synchronous
@@ -1366,10 +1400,10 @@ class x {
1366
1400
  */
1367
1401
  stageSlice(e, t, s) {
1368
1402
  const n = this.state[e], r = this.reducers[e].reduce(n, t);
1369
- if (Q(r)) return r;
1403
+ if (V(r)) return r;
1370
1404
  if (n === r) return null;
1371
- const o = I(n, r);
1372
- if (o.length === 0) return null;
1405
+ const c = I(n, r);
1406
+ if (c.length === 0) return null;
1373
1407
  const l = t.payload, i = process.env.NODE_ENV !== "production" && l !== null && typeof l == "object" ? {
1374
1408
  watch: l,
1375
1409
  onFound: () => {
@@ -1383,7 +1417,7 @@ class x {
1383
1417
  name: e,
1384
1418
  prev: n,
1385
1419
  frozen: R(r, i),
1386
- leafPaths: o
1420
+ leafPaths: c
1387
1421
  }), null;
1388
1422
  }
1389
1423
  /**
@@ -1415,18 +1449,18 @@ class x {
1415
1449
  this.changedPathSink.push(r ? `${n.name}.${r}` : n.name);
1416
1450
  for (const n of e) {
1417
1451
  const r = /* @__PURE__ */ new Set();
1418
- for (const o of n.leafPaths) {
1419
- if (o === "") {
1452
+ for (const c of n.leafPaths) {
1453
+ if (c === "") {
1420
1454
  r.add("");
1421
1455
  continue;
1422
1456
  }
1423
- for (const l of x.buildAncestorPaths(o)) r.add(l);
1457
+ for (const l of x.buildAncestorPaths(c)) r.add(l);
1424
1458
  }
1425
- for (const o of r)
1426
- this.connectorBus.emitWith(n.name, o, () => ({
1427
- oldValue: this.getAtPath(n.prev, o),
1428
- newValue: this.getAtPath(n.frozen, o),
1429
- path: o,
1459
+ for (const c of r)
1460
+ this.connectorBus.emitWith(n.name, c, () => ({
1461
+ oldValue: this.getAtPath(n.prev, c),
1462
+ newValue: this.getAtPath(n.frozen, c),
1463
+ path: c,
1430
1464
  // Provenance, built inside the same lazy factory as the values: a subscriber that
1431
1465
  // needs to know why a value moved no longer has to mirror the cause into state and
1432
1466
  // keep it there twice.
@@ -1454,10 +1488,10 @@ class x {
1454
1488
  }), t = [];
1455
1489
  for (const [l, i] of this.effects) {
1456
1490
  if (i.size === 0) continue;
1457
- const [a, d] = l.split("::");
1458
- for (const u of i) {
1459
- const f = this.effectMeta.get(u);
1460
- t.push({ channel: a, type: d, name: f?.name, description: f?.description });
1491
+ const [a, u] = l.split("::");
1492
+ for (const d of i) {
1493
+ const h = this.effectMeta.get(d);
1494
+ t.push({ channel: a, type: u, name: h?.name, description: h?.description });
1461
1495
  }
1462
1496
  }
1463
1497
  for (const l of this.patternEffects) {
@@ -1483,30 +1517,30 @@ class x {
1483
1517
  const r = [];
1484
1518
  for (const [l, i] of this.committedEventSubscribers) {
1485
1519
  if (i.size === 0) continue;
1486
- const [a, d] = l.split("::");
1487
- for (let u = 0; u < i.size; u++)
1488
- r.push({ channel: a, type: d, phase: "committed" });
1520
+ const [a, u] = l.split("::");
1521
+ for (let d = 0; d < i.size; d++)
1522
+ r.push({ channel: a, type: u, phase: "committed" });
1489
1523
  }
1490
1524
  for (const [l, i] of this.uncommittedEventSubscribers) {
1491
1525
  if (i.size === 0) continue;
1492
- const [a, d] = l.split("::");
1493
- for (let u = 0; u < i.size; u++)
1494
- r.push({ channel: a, type: d, phase: "uncommitted" });
1526
+ const [a, u] = l.split("::");
1527
+ for (let d = 0; d < i.size; d++)
1528
+ r.push({ channel: a, type: u, phase: "uncommitted" });
1495
1529
  }
1496
1530
  for (const [l, i] of this.allEventSubscribers) {
1497
1531
  if (i.size === 0) continue;
1498
- const [a, d] = l.split("::");
1499
- for (let u = 0; u < i.size; u++)
1500
- r.push({ channel: a, type: d, phase: "all" });
1532
+ const [a, u] = l.split("::");
1533
+ for (let d = 0; d < i.size; d++)
1534
+ r.push({ channel: a, type: u, phase: "all" });
1501
1535
  }
1502
- const o = this.listeners.size;
1536
+ const c = this.listeners.size;
1503
1537
  return {
1504
1538
  reducers: e,
1505
1539
  effects: t,
1506
1540
  middleware: s,
1507
1541
  atomic: n,
1508
1542
  event: r,
1509
- coarse: o,
1543
+ coarse: c,
1510
1544
  dedupHits: this.dedupCount,
1511
1545
  queueDepth: this.reduceQueue.length + this.inFlightEffects
1512
1546
  };
@@ -1533,34 +1567,34 @@ class x {
1533
1567
  );
1534
1568
  const t = this.state, s = e, n = { ...this.state };
1535
1569
  let r = !1;
1536
- Object.keys(this.reducers).forEach((o) => {
1537
- const l = t?.[o], i = s?.[o];
1570
+ Object.keys(this.reducers).forEach((c) => {
1571
+ const l = t?.[c], i = s?.[c];
1538
1572
  if (i === void 0) {
1539
1573
  process.env.NODE_ENV !== "production" && console.warn(
1540
1574
  `[yoltra] External state is missing slice "${String(
1541
- o
1575
+ c
1542
1576
  )}"; retaining its current value. Time-travel snapshots should contain all slices.`
1543
1577
  );
1544
1578
  return;
1545
1579
  }
1546
1580
  if (l === i) return;
1547
1581
  const a = R(i);
1548
- n[o] = a, r = !0;
1549
- const d = I(l, i);
1550
- if (d.length === 0) return;
1551
- const u = /* @__PURE__ */ new Set();
1552
- for (const f of d) {
1553
- if (f === "") {
1554
- u.add("");
1582
+ n[c] = a, r = !0;
1583
+ const u = I(l, i);
1584
+ if (u.length === 0) return;
1585
+ const d = /* @__PURE__ */ new Set();
1586
+ for (const h of u) {
1587
+ if (h === "") {
1588
+ d.add("");
1555
1589
  continue;
1556
1590
  }
1557
- for (const m of x.buildAncestorPaths(f)) u.add(m);
1591
+ for (const p of x.buildAncestorPaths(h)) d.add(p);
1558
1592
  }
1559
- for (const f of u) {
1560
- const m = this.getAtPath(l, f), h = this.getAtPath(a, f);
1561
- this.connectorBus.emit(o, f, { oldValue: m, newValue: h, path: f });
1593
+ for (const h of d) {
1594
+ const p = this.getAtPath(l, h), f = this.getAtPath(a, h);
1595
+ this.connectorBus.emit(c, h, { oldValue: p, newValue: f, path: h });
1562
1596
  }
1563
- }), r && (this.state = n), r && this.listeners.forEach((o) => o());
1597
+ }), r && (this.state = n), r && this.listeners.forEach((c) => c());
1564
1598
  }
1565
1599
  /**
1566
1600
  * Replays a sequence of events from a snapshot through reducers and event
@@ -1583,20 +1617,20 @@ class x {
1583
1617
  for (const s of t) {
1584
1618
  const n = s, r = [];
1585
1619
  this.stagingSink = r;
1586
- let o = null;
1620
+ let c = null;
1587
1621
  try {
1588
- this.reducerBus.emit(n.channel, n.type, n.payload, n), o = this.stagedRejection;
1622
+ this.reducerBus.emit(n.channel, n.type, n.payload, n), c = this.stagedRejection;
1589
1623
  for (const [i, a] of this.patternReducers) {
1590
- if (o !== null) break;
1591
- if (this.matchesWhen(a, n)) {
1592
- const d = this.stageSliceGuarded(i, n, r);
1593
- d !== null && (o = d);
1624
+ if (c !== null) break;
1625
+ if (k(a, n)) {
1626
+ const u = this.stageSliceGuarded(i, n, r);
1627
+ u !== null && (c = u);
1594
1628
  }
1595
1629
  }
1596
1630
  } finally {
1597
1631
  this.stagingSink = null, this.stagedRejection = null, this.stagedRejectedBy = "";
1598
1632
  }
1599
- const l = o === null && this.commitStaged(r, n);
1633
+ const l = c === null && this.commitStaged(r, n);
1600
1634
  this.notifyEventSubscribers(n, "committed"), l && (this.notifyEventSubscribers(n, "written"), this.listeners.forEach((i) => i()));
1601
1635
  }
1602
1636
  }
@@ -1659,14 +1693,14 @@ class x {
1659
1693
  * @internal
1660
1694
  */
1661
1695
  async emitCaused(e, t, s, n, r) {
1662
- const o = r?.dedupKey, l = this.dedupConfig.windowMs;
1663
- if (r?.skipDedup !== !0 && (l > 0 || o !== void 0)) {
1664
- const m = o !== void 0 && l <= 0 ? D : l, h = o !== void 0 ? `${t}::${s}::#${o}` : this.fingerprint(t, s, n);
1665
- if (this.shouldDedupe(h, m))
1666
- return $;
1696
+ const c = r?.dedupKey, l = this.dedupConfig.windowMs;
1697
+ if (r?.skipDedup !== !0 && (l > 0 || c !== void 0)) {
1698
+ const p = c !== void 0 && l <= 0 ? A : l, f = c !== void 0 ? `${t}::${s}::#${c}` : this.fingerprint(t, s, n);
1699
+ if (this.shouldDedupe(f, p))
1700
+ return S;
1667
1701
  }
1668
- const i = r?.id ?? this.idFactory(), a = this.currentEvent ?? e, d = a === null ? 0 : a.depth + 1;
1669
- if (a !== null && d > this.maxReduceDepth)
1702
+ const i = r?.id ?? this.idFactory(), a = this.currentEvent ?? e, u = a === null ? 0 : a.depth + 1;
1703
+ if (a !== null && u > this.maxReduceDepth)
1670
1704
  return this.reportCascade(
1671
1705
  "maxReduceDepth",
1672
1706
  this.maxReduceDepth,
@@ -1677,14 +1711,14 @@ class x {
1677
1711
  id: i,
1678
1712
  ...r?.meta !== void 0 ? { meta: r.meta } : {},
1679
1713
  parentId: a.id,
1680
- depth: d
1714
+ depth: u
1681
1715
  },
1682
- d,
1716
+ u,
1683
1717
  a.chain
1684
- ), $;
1685
- let u;
1686
- const f = new Promise((m) => {
1687
- u = m;
1718
+ ), S;
1719
+ let d;
1720
+ const h = new Promise((p) => {
1721
+ d = p;
1688
1722
  });
1689
1723
  return this.reduceQueue.push({
1690
1724
  channel: t,
@@ -1692,11 +1726,11 @@ class x {
1692
1726
  payload: n,
1693
1727
  id: i,
1694
1728
  meta: r?.meta,
1695
- resolve: u,
1729
+ resolve: d,
1696
1730
  // Only carried for caused events, so a root event's object stays byte-identical to one
1697
1731
  // built before causality existed — the same rule `meta` follows.
1698
- ...a !== null ? { parentId: a.id, depth: d, chain: a.chain } : {}
1699
- }), this.drainReduce(), f;
1732
+ ...a !== null ? { parentId: a.id, depth: u, chain: a.chain } : {}
1733
+ }), this.drainReduce(), h;
1700
1734
  }
1701
1735
  /**
1702
1736
  * Drains the reduce queue **synchronously**. For each event it runs middleware,
@@ -1713,47 +1747,47 @@ class x {
1713
1747
  this.isReducing = !0, this.transitionsThisDrain = 0;
1714
1748
  try {
1715
1749
  for (; this.reduceQueue.length > 0; ) {
1716
- const e = this.reduceQueue.shift(), { channel: t, type: s, payload: n, id: r, meta: o, resolve: l, parentId: i, depth: a, chain: d } = e, u = {
1750
+ const e = this.reduceQueue.shift(), { channel: t, type: s, payload: n, id: r, meta: c, resolve: l, parentId: i, depth: a, chain: u } = e, d = {
1717
1751
  channel: t,
1718
1752
  type: s,
1719
1753
  payload: n,
1720
1754
  id: r,
1721
- ...o !== void 0 ? { meta: o } : {},
1755
+ ...c !== void 0 ? { meta: c } : {},
1722
1756
  ...i !== void 0 ? { parentId: i, depth: a } : {}
1723
1757
  };
1724
1758
  if (i !== void 0 && ++this.transitionsThisDrain > this.maxTransitionsPerDrain) {
1725
1759
  this.reportCascade(
1726
1760
  "maxTransitionsPerDrain",
1727
1761
  this.maxTransitionsPerDrain,
1728
- u,
1762
+ d,
1729
1763
  a,
1730
- d
1731
- ), l($);
1764
+ u
1765
+ ), l(S);
1732
1766
  continue;
1733
1767
  }
1734
1768
  this.currentEvent = {
1735
1769
  id: r,
1736
1770
  depth: a ?? 0,
1737
- chain: [...d ?? [], r].slice(-z)
1771
+ chain: [...u ?? [], r].slice(-z)
1738
1772
  };
1739
- const f = this.instrumentObservers.size > 0, m = f ? this.state : void 0, h = f ? [] : void 0;
1740
- h !== void 0 && (this.changedPathSink = h);
1741
- const y = f ? A() : 0;
1742
- let g = $;
1773
+ const h = this.instrumentObservers.size > 0, p = h ? this.state : void 0, f = h ? [] : void 0;
1774
+ f !== void 0 && (this.changedPathSink = f);
1775
+ const m = h ? _() : 0;
1776
+ let y = S;
1743
1777
  try {
1744
- g = this.applyEventSync(u);
1745
- } catch (w) {
1746
- console.error("Emit reduce error:", w);
1778
+ y = this.applyEventSync(d);
1779
+ } catch (g) {
1780
+ console.error("Emit reduce error:", g);
1747
1781
  } finally {
1748
- f && (this.changedPathSink = null), this.currentEvent = null;
1782
+ h && (this.changedPathSink = null), this.currentEvent = null;
1749
1783
  }
1750
- f && this.emitInstrumentation(
1751
- u,
1752
- g,
1753
- h ?? [],
1754
- m,
1755
- A() - y
1756
- ), this.runEventEffects(u, g, l);
1784
+ h && this.emitInstrumentation(
1785
+ d,
1786
+ y,
1787
+ f ?? [],
1788
+ p,
1789
+ _() - m
1790
+ ), this.runEventEffects(d, y, l);
1757
1791
  }
1758
1792
  } finally {
1759
1793
  this.isReducing = !1;
@@ -1771,20 +1805,20 @@ class x {
1771
1805
  * @internal
1772
1806
  */
1773
1807
  applyEventSync(e) {
1774
- for (const o of this.middleware) {
1775
- const l = this.getMiddlewareWhen(o);
1776
- if (!this.matchesWhen(l, e)) continue;
1777
- const i = this.getMiddlewareFunction(o);
1808
+ for (const c of this.middleware) {
1809
+ const l = se(c);
1810
+ if (!k(l, e)) continue;
1811
+ const i = ne(c);
1778
1812
  let a;
1779
1813
  try {
1780
1814
  a = i(this.state, e, this.emit), process.env.NODE_ENV !== "production" && typeof a?.then == "function" && console.error(
1781
1815
  `[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.`
1782
1816
  );
1783
- } catch (d) {
1784
- console.error("Middleware error:", d), a = !1;
1817
+ } catch (u) {
1818
+ console.error("Middleware error:", u), a = !1;
1785
1819
  }
1786
1820
  if (!a)
1787
- return this.notifyEventSubscribers(e, "uncommitted"), $;
1821
+ return this.notifyEventSubscribers(e, "uncommitted"), S;
1788
1822
  }
1789
1823
  const t = [];
1790
1824
  this.stagingSink = t;
@@ -1796,11 +1830,11 @@ class x {
1796
1830
  e.payload,
1797
1831
  e
1798
1832
  ), s = this.stagedRejection, n = this.stagedRejectedBy;
1799
- for (const [o, l] of this.patternReducers) {
1833
+ for (const [c, l] of this.patternReducers) {
1800
1834
  if (s !== null) break;
1801
- if (this.matchesWhen(l, e)) {
1802
- const i = this.stageSliceGuarded(o, e, t);
1803
- i !== null && (s = i, n = o);
1835
+ if (k(l, e)) {
1836
+ const i = this.stageSliceGuarded(c, e, t);
1837
+ i !== null && (s = i, n = c);
1804
1838
  }
1805
1839
  }
1806
1840
  } finally {
@@ -1809,7 +1843,7 @@ class x {
1809
1843
  if (s !== null)
1810
1844
  return this.onRejected?.(s, e, n), this.notifyEventSubscribers(e, "committed"), { committed: !0, written: !1, rejected: s };
1811
1845
  const r = this.commitStaged(t, e);
1812
- return this.notifyEventSubscribers(e, "committed"), r && (this.notifyEventSubscribers(e, "written"), this.listeners.forEach((o) => o())), r ? se : ne;
1846
+ return this.notifyEventSubscribers(e, "committed"), r && (this.notifyEventSubscribers(e, "written"), this.listeners.forEach((c) => c())), r ? ce : oe;
1813
1847
  }
1814
1848
  /**
1815
1849
  * Runs a single committed event's effects as an **independent async task**,
@@ -1848,9 +1882,9 @@ class x {
1848
1882
  * @internal
1849
1883
  */
1850
1884
  emitInstrumentation(e, t, s, n, r) {
1851
- const o = {}, l = {};
1885
+ const c = {}, l = {};
1852
1886
  for (const a of s)
1853
- o[a] = this.getAtPath(n, a), l[a] = this.getAtPath(this.state, a);
1887
+ c[a] = this.getAtPath(n, a), l[a] = this.getAtPath(this.state, a);
1854
1888
  const i = {
1855
1889
  event: {
1856
1890
  id: e.id,
@@ -1863,7 +1897,7 @@ class x {
1863
1897
  },
1864
1898
  committed: t.committed,
1865
1899
  changedPaths: s,
1866
- prevValues: o,
1900
+ prevValues: c,
1867
1901
  nextValues: l,
1868
1902
  reduceTimeMs: r,
1869
1903
  // Present only when a reducer refused, so an observer can tell a refusal from a veto —
@@ -1873,8 +1907,8 @@ class x {
1873
1907
  for (const a of [...this.instrumentObservers])
1874
1908
  try {
1875
1909
  a(i);
1876
- } catch (d) {
1877
- console.error("Instrumentation observer error:", d);
1910
+ } catch (u) {
1911
+ console.error("Instrumentation observer error:", u);
1878
1912
  }
1879
1913
  }
1880
1914
  /**
@@ -1908,8 +1942,8 @@ class x {
1908
1942
  connect(e, t, s) {
1909
1943
  const n = this.connectorBus.on(e.reducer, e.property, t);
1910
1944
  if (s?.immediate === !0) {
1911
- const r = this.state[e.reducer], o = e.property.includes("*") ? "" : e.property;
1912
- t({ oldValue: void 0, newValue: this.getAtPath(r, o), path: o });
1945
+ const r = this.state[e.reducer], c = e.property.includes("*") ? "" : e.property;
1946
+ t({ oldValue: void 0, newValue: this.getAtPath(r, c), path: c });
1913
1947
  }
1914
1948
  return n;
1915
1949
  }
@@ -1960,10 +1994,10 @@ class x {
1960
1994
  * @public
1961
1995
  */
1962
1996
  onEvent(e, t, s, n = "committed") {
1963
- const r = `${e}::${String(t)}`, o = n === "committed" ? this.committedEventSubscribers : n === "uncommitted" ? this.uncommittedEventSubscribers : n === "written" ? this.writtenEventSubscribers : this.allEventSubscribers;
1964
- return o.has(r) || o.set(r, /* @__PURE__ */ new Set()), o.get(r).add(s), () => {
1965
- const l = o.get(r);
1966
- l && (l.delete(s), l.size === 0 && o.delete(r));
1997
+ const r = `${e}::${String(t)}`, c = n === "committed" ? this.committedEventSubscribers : n === "uncommitted" ? this.uncommittedEventSubscribers : n === "written" ? this.writtenEventSubscribers : this.allEventSubscribers;
1998
+ return c.has(r) || c.set(r, /* @__PURE__ */ new Set()), c.get(r).add(s), () => {
1999
+ const l = c.get(r);
2000
+ l && (l.delete(s), l.size === 0 && c.delete(r));
1967
2001
  };
1968
2002
  }
1969
2003
  /**
@@ -2168,13 +2202,7 @@ class x {
2168
2202
  * the terminal event from ever being sent. Un-iterated progress therefore buffers to
2169
2203
  * `highWaterMark` and is then counted on {@link CallHandle.dropped} rather than blocking.
2170
2204
  *
2171
- * **This is a local primitive.** A reply cannot reach it from a federated peer: the federation
2172
- * envelope carries neither `meta` nor `parentId`, and ingress namespaces the channel, so
2173
- * neither correlation nor the reply route survives the hop. That is not an oversight to route
2174
- * around — federation answers cross-node request/reply with typed peer *queries*, which are
2175
- * gated by a responder policy that may concede or deny. A call that federated silently would
2176
- * turn that access decision into an accident of which channel someone named. Ask a peer with a
2177
- * query; use `call` within a process.
2205
+ * **This is a local primitive.**
2178
2206
  *
2179
2207
  * @example Timeout is idle, not total
2180
2208
  * ```ts
@@ -2191,58 +2219,13 @@ class x {
2191
2219
  * @public
2192
2220
  */
2193
2221
  call(e, t, s, n) {
2194
- const { channel: r, isTerminal: o } = q(n.reply), l = n.timeoutMs ?? ee, i = new G(n.highWaterMark ?? te), a = this.idFactory();
2195
- let d, u, f = !1;
2196
- const m = new Promise((b, S) => {
2197
- d = b, u = S;
2198
- });
2199
- m.catch(() => {
2200
- });
2201
- let h = null, y = null;
2202
- const g = (b, S = !1) => {
2203
- f || (f = !0, h !== null && clearTimeout(h), h = null, y?.(), y = null, S ? i.end() : i.close(), n.signal?.removeEventListener("abort", w), b());
2204
- };
2205
- function w() {
2206
- g(() => u(new C(String(n.signal?.reason ?? "signal aborted"))));
2207
- }
2208
- const k = () => {
2209
- h !== null && clearTimeout(h), h = setTimeout(() => {
2210
- g(() => u(new J(e, t, l)));
2211
- }, l), h.unref?.();
2212
- };
2213
- return y = this.registerEffect({
2214
- // A pattern effect on the reply channel: which types are terminal is known, which are
2215
- // progress is not, so the filter cannot be a key list.
2216
- when: { channel: r },
2217
- effect: async (b) => {
2218
- if (!f && Y(b, a, n.correlationId)) {
2219
- if (k(), o(String(b.type))) {
2220
- g(() => d(b), !0);
2221
- return;
2222
- }
2223
- await i.put(b);
2224
- }
2225
- }
2226
- }), n.signal !== void 0 && (n.signal.aborted ? w() : n.signal.addEventListener("abort", w, { once: !0 })), k(), this.emit(e, t, s, {
2227
- id: a,
2228
- ...n.correlationId !== void 0 ? { meta: { correlationId: n.correlationId } } : {}
2229
- }), {
2230
- then: (b, S) => m.then(b, S),
2231
- catch: (b) => m.catch(b),
2232
- finally: (b) => m.finally(b),
2233
- get dropped() {
2234
- return i.droppedCount;
2235
- },
2236
- cancel: (b = "cancelled") => {
2237
- g(() => u(new C(b)));
2238
- },
2239
- [Symbol.asyncIterator]: () => (i.beginConsuming(), {
2240
- next: () => i.take(),
2241
- // Called by `for await` on `break`, `return` or a throw. Without it, abandoning the
2242
- // loop would leave the effect registered and the producer parked for good.
2243
- return: async () => (i.close(), { value: void 0, done: !0 })
2244
- })
2245
- };
2222
+ return Z(
2223
+ { idFactory: this.idFactory, registerEffect: this.registerEffect, emit: this.emit },
2224
+ e,
2225
+ t,
2226
+ s,
2227
+ n
2228
+ );
2246
2229
  }
2247
2230
  registerEffect(e) {
2248
2231
  const { effect: t, meta: s, when: n } = e, r = [];
@@ -2252,7 +2235,7 @@ class x {
2252
2235
  this.patternEffects.delete(i);
2253
2236
  };
2254
2237
  }
2255
- const l = this.normalizeEventKeys(e);
2238
+ const l = D(e);
2256
2239
  if (l.length === 0 && !n) {
2257
2240
  const i = { effect: t, when: { any: !0 } };
2258
2241
  return this.patternEffects.add(i), () => {
@@ -2260,10 +2243,10 @@ class x {
2260
2243
  };
2261
2244
  }
2262
2245
  for (const [i, a] of l) {
2263
- const d = `${String(i)}::${String(a)}`;
2264
- this.effects.has(d) || this.effects.set(d, /* @__PURE__ */ new Set()), this.effects.get(d).add(t), r.push(() => {
2265
- const u = this.effects.get(d);
2266
- u && (u.delete(t), u.size === 0 && this.effects.delete(d));
2246
+ const u = `${String(i)}::${String(a)}`;
2247
+ this.effects.has(u) || this.effects.set(u, /* @__PURE__ */ new Set()), this.effects.get(u).add(t), r.push(() => {
2248
+ const d = this.effects.get(u);
2249
+ d && (d.delete(t), d.size === 0 && this.effects.delete(u));
2267
2250
  });
2268
2251
  }
2269
2252
  return () => {
@@ -2292,10 +2275,10 @@ class x {
2292
2275
  * @public
2293
2276
  */
2294
2277
  onEffect(e, t, s) {
2295
- const n = async (r, o, l) => {
2278
+ const n = async (r, c, l) => {
2296
2279
  if (r.channel !== e || r.type !== t) return;
2297
2280
  const i = r;
2298
- return s(i.payload, o, l, i);
2281
+ return s(i.payload, c, l, i);
2299
2282
  };
2300
2283
  return this.registerEffect({
2301
2284
  when: { keys: [[e, t]] },
@@ -2361,9 +2344,9 @@ class x {
2361
2344
  * @public
2362
2345
  */
2363
2346
  replaceReducers(e, t = {}) {
2364
- const s = t.preserveState !== !1, n = new Set(Object.keys(this.reducers)), r = Object.entries(e), o = new Set(r.map(([l]) => l));
2347
+ const s = t.preserveState !== !1, n = new Set(Object.keys(this.reducers)), r = Object.entries(e), c = new Set(r.map(([l]) => l));
2365
2348
  for (const l of n)
2366
- o.has(l) || this.unmountSlice(l, { deleteState: !0 });
2349
+ c.has(l) || this.unmountSlice(l, { deleteState: !0 });
2367
2350
  for (const [l, i] of r)
2368
2351
  n.has(l) ? (this.unmountSlice(l, { deleteState: !1 }), this.mountSlice(l, i, { preserveState: s })) : this.mountSlice(l, i, { preserveState: !1 });
2369
2352
  }
@@ -2398,35 +2381,35 @@ class x {
2398
2381
  * @internal
2399
2382
  */
2400
2383
  mountSlice(e, t, s) {
2401
- const n = e, { reducer: r, state: o, when: l } = t;
2402
- if (this.reducers[e] = new V(r), (!s.preserveState || this.state[n] === void 0) && (this.state = {
2384
+ const n = e, { reducer: r, state: c, when: l } = t;
2385
+ if (this.reducers[e] = new L(r), (!s.preserveState || this.state[n] === void 0) && (this.state = {
2403
2386
  ...this.state,
2404
- [n]: R(X(n, o))
2387
+ [n]: R(re(n, c))
2405
2388
  }), l && ("any" in l && l.any === !0 || "channel" in l || "channels" in l)) {
2406
2389
  this.patternReducers.set(e, l), this.sliceUnsubs.set(n, []);
2407
2390
  return;
2408
2391
  }
2409
- const a = this.normalizeEventKeys(t);
2392
+ const a = D(t);
2410
2393
  if (a.length === 0 && !l) {
2411
2394
  this.patternReducers.set(e, { any: !0 }), this.sliceUnsubs.set(n, []);
2412
2395
  return;
2413
2396
  }
2414
- const d = [];
2415
- for (const [u, f] of a) {
2416
- const m = this.reducerBus.on(u, f, (h, y) => {
2417
- const g = y ?? {
2418
- channel: u,
2419
- type: f,
2420
- payload: h,
2397
+ const u = [];
2398
+ for (const [d, h] of a) {
2399
+ const p = this.reducerBus.on(d, h, (f, m) => {
2400
+ const y = m ?? {
2401
+ channel: d,
2402
+ type: h,
2403
+ payload: f,
2421
2404
  id: this.idFactory()
2422
2405
  };
2423
2406
  if (this.stagingSink === null) return;
2424
- const w = this.stageSliceGuarded(e, g, this.stagingSink);
2425
- w !== null && this.stagedRejection === null && (this.stagedRejection = w, this.stagedRejectedBy = e);
2407
+ const g = this.stageSliceGuarded(e, y, this.stagingSink);
2408
+ g !== null && this.stagedRejection === null && (this.stagedRejection = g, this.stagedRejectedBy = e);
2426
2409
  });
2427
- d.push(m);
2410
+ u.push(p);
2428
2411
  }
2429
- this.sliceUnsubs.set(n, d);
2412
+ this.sliceUnsubs.set(n, u);
2430
2413
  }
2431
2414
  /**
2432
2415
  * Unmounts a slice: disposes reducer-bus listeners, removes reducer,
@@ -2445,32 +2428,16 @@ class x {
2445
2428
  for (const r of n)
2446
2429
  try {
2447
2430
  r();
2448
- } catch (o) {
2449
- console.error(`[Store error]: ${o}`);
2431
+ } catch (c) {
2432
+ console.error(`[Store error]: ${c}`);
2450
2433
  }
2451
2434
  this.sliceUnsubs.delete(s);
2452
2435
  }
2453
2436
  if (delete this.reducers[e], t.deleteState) {
2454
- const { [s]: r, ...o } = this.state;
2455
- this.state = o;
2437
+ const { [s]: r, ...c } = this.state;
2438
+ this.state = c;
2456
2439
  }
2457
2440
  }
2458
- /**
2459
- * Normalizes event targeting from `when` to an array of EventKeys.
2460
- *
2461
- * @param spec - Object with an optional `when` matcher.
2462
- * @returns Array of `[channel, type]` pairs.
2463
- *
2464
- * @internal
2465
- */
2466
- normalizeEventKeys(e) {
2467
- if (e.when) {
2468
- const t = e.when;
2469
- if ("keys" in t)
2470
- return t.keys;
2471
- }
2472
- return [];
2473
- }
2474
2441
  /**
2475
2442
  * Reads a dotted path from an object (supports numeric array indices via string keys).
2476
2443
  *
@@ -2478,17 +2445,14 @@ class x {
2478
2445
  * @param path - Dotted path; leading dot is ignored.
2479
2446
  * @returns The value at the path, or `undefined`.
2480
2447
  *
2448
+ * @remarks
2449
+ * A member rather than a bare import: a test replaces this on the instance to count how many
2450
+ * walks describing a change costs, which only works while the callers go through `this`.
2451
+ *
2481
2452
  * @internal
2482
2453
  */
2483
2454
  getAtPath(e, t) {
2484
- if (!t) return e;
2485
- const n = (t[0] === "." ? t.slice(1) : t).split(".");
2486
- let r = e;
2487
- for (const o of n) {
2488
- if (r == null) return;
2489
- r = r[o];
2490
- }
2491
- return r;
2455
+ return ee(e, t);
2492
2456
  }
2493
2457
  /**
2494
2458
  * Builds ancestor paths for a dotted path.
@@ -2506,72 +2470,68 @@ class x {
2506
2470
  * @public
2507
2471
  */
2508
2472
  static buildAncestorPaths(e) {
2509
- if (!e) return [];
2510
- const s = (e[0] === "." ? e.slice(1) : e).split("."), n = [];
2511
- for (let r = 0; r < s.length; r++)
2512
- n.push(s.slice(0, r + 1).join("."));
2513
- return n;
2473
+ return te(e);
2514
2474
  }
2515
2475
  }
2516
- function de(c) {
2476
+ function he(o) {
2517
2477
  return new x({
2518
- ...c,
2519
- reducer: c.reducer ?? {},
2520
- middleware: c.middleware ?? [],
2521
- effects: c.effects ?? []
2478
+ ...o,
2479
+ reducer: o.reducer ?? {},
2480
+ middleware: o.middleware ?? [],
2481
+ effects: o.effects ?? []
2522
2482
  });
2523
2483
  }
2524
- const ue = (c) => (e, t) => t.map((s) => [e, s]), fe = () => (c) => c, _ = /* @__PURE__ */ new Set();
2525
- function re(c) {
2526
- const e = String(c);
2527
- _.has(e) || (_.add(e), console.warn(
2484
+ const pe = (o) => (e, t) => t.map((s) => [e, s]), me = () => (o) => o, j = /* @__PURE__ */ new Set();
2485
+ function ae(o) {
2486
+ const e = String(o);
2487
+ j.has(e) || (j.add(e), console.warn(
2528
2488
  `[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.`
2529
2489
  ));
2530
2490
  }
2531
- function ie(c, e) {
2532
- if (c.length !== e.length) return e;
2533
- for (let t = 0; t < c.length; t++)
2534
- if (c[t] !== e[t]) return e;
2535
- return c;
2491
+ function le(o, e) {
2492
+ if (o.length !== e.length) return e;
2493
+ for (let t = 0; t < o.length; t++)
2494
+ if (o[t] !== e[t]) return e;
2495
+ return o;
2536
2496
  }
2537
- function he(c = {}) {
2538
- const e = c.selectId ?? ((i) => i.id), { sortComparer: t } = c, s = (i, a) => {
2497
+ function ye(o = {}) {
2498
+ const e = o.selectId ?? ((i) => i.id), { sortComparer: t } = o, s = (i, a) => {
2539
2499
  if (t === void 0) return a;
2540
- const d = [...a].sort((u, f) => {
2541
- const m = i.entities[u], h = i.entities[f];
2542
- return m === void 0 || h === void 0 ? 0 : t(m, h);
2500
+ const u = [...a].sort((d, h) => {
2501
+ const p = i.entities[d], f = i.entities[h];
2502
+ return p === void 0 || f === void 0 ? 0 : t(p, f);
2543
2503
  });
2544
- return ie(a, d);
2545
- }, n = (i, a, d) => {
2546
- const u = { ...i, entities: a, ids: d };
2547
- return { ...u, ids: s(u, d) };
2548
- }, r = (i, a, d) => {
2549
- let u = null, f = null;
2550
- for (const m of a) {
2551
- const h = e(m);
2552
- process.env.NODE_ENV !== "production" && String(h).includes(".") && re(h);
2553
- const y = (u ?? i.entities)[h];
2554
- if (y !== void 0 && d === "add") continue;
2555
- const g = y !== void 0 && d === "upsert" ? { ...y, ...m } : m;
2556
- u ?? (u = { ...i.entities }), u[h] = g, y === void 0 && (f ?? (f = [...i.ids]), f.push(h));
2504
+ return le(a, u);
2505
+ }, n = (i, a, u) => {
2506
+ const d = { ...i, entities: a, ids: u };
2507
+ return { ...d, ids: s(d, u) };
2508
+ }, r = (i, a, u) => {
2509
+ let d = null, h = null;
2510
+ for (const p of a) {
2511
+ const f = e(p);
2512
+ process.env.NODE_ENV !== "production" && String(f).includes(".") && ae(f);
2513
+ const m = (d ?? i.entities)[f];
2514
+ if (m !== void 0 && u === "add") continue;
2515
+ const y = m !== void 0 && u === "upsert" ? { ...m, ...p } : p;
2516
+ d ??= { ...i.entities }, d[f] = y, m === void 0 && (h ??= [...i.ids], h.push(f));
2557
2517
  }
2558
- return u === null ? i : n(i, u, f ?? i.ids);
2559
- }, o = (i, a) => {
2560
- let d = null;
2561
- for (const { id: u, changes: f } of a) {
2562
- const m = (d ?? i.entities)[u];
2563
- m !== void 0 && (d ?? (d = { ...i.entities }), d[u] = { ...m, ...f });
2518
+ return d === null ? i : n(i, d, h ?? i.ids);
2519
+ }, c = (i, a) => {
2520
+ let u = null;
2521
+ for (const { id: d, changes: h } of a) {
2522
+ const p = (u ?? i.entities)[d];
2523
+ p !== void 0 && (u ??= { ...i.entities }, u[d] = { ...p, ...h });
2564
2524
  }
2565
- return d === null ? i : n(i, d, i.ids);
2525
+ return u === null ? i : n(i, u, i.ids);
2566
2526
  }, l = (i, a) => {
2567
- const d = new Set(a.filter((f) => i.entities[f] !== void 0));
2568
- if (d.size === 0) return i;
2569
- const u = { ...i.entities };
2570
- for (const f of d) delete u[f];
2527
+ const u = new Set(a.filter((h) => i.entities[h] !== void 0));
2528
+ if (u.size === 0) return i;
2529
+ const d = { ...i.entities };
2530
+ for (const h of u) delete d[h];
2571
2531
  return n(
2572
2532
  i,
2573
- u,
2574
- i.ids.filter((f) => !d.has(f))
2533
+ d,
2534
+ i.ids.filter((h) => !u.has(h))
2575
2535
  );
2576
2536
  };
2577
2537
  return {
@@ -2584,15 +2544,15 @@ function he(c = {}) {
2584
2544
  setOne: (i, a) => r(i, [a], "set"),
2585
2545
  setMany: (i, a) => r(i, a, "set"),
2586
2546
  setAll: (i, a) => {
2587
- const d = {}, u = [];
2588
- for (const f of a) {
2589
- const m = e(f);
2590
- d[m] === void 0 && u.push(m), d[m] = f;
2547
+ const u = {}, d = [];
2548
+ for (const h of a) {
2549
+ const p = e(h);
2550
+ u[p] === void 0 && d.push(p), u[p] = h;
2591
2551
  }
2592
- return n(i, d, u);
2552
+ return n(i, u, d);
2593
2553
  },
2594
- updateOne: (i, a) => o(i, [a]),
2595
- updateMany: (i, a) => o(i, a),
2554
+ updateOne: (i, a) => c(i, [a]),
2555
+ updateMany: (i, a) => c(i, a),
2596
2556
  upsertOne: (i, a) => r(i, [a], "upsert"),
2597
2557
  upsertMany: (i, a) => r(i, a, "upsert"),
2598
2558
  removeOne: (i, a) => l(i, [a]),
@@ -2608,76 +2568,76 @@ function he(c = {}) {
2608
2568
  anyField: (i) => `entities.*.${i}`
2609
2569
  };
2610
2570
  }
2611
- const E = "$yoltra";
2612
- function B(c, e = {}) {
2571
+ const w = "$yoltra";
2572
+ function H(o, e = {}) {
2613
2573
  const t = e.maxNodes ?? 1e5, s = e.sanitize, n = [], r = /* @__PURE__ */ new Map();
2614
- let o = 0, l = !1;
2615
- function i(d, u) {
2616
- if (s !== void 0 && (d = s(u, d)), o += 1, o > t)
2617
- return l = !0, { [E]: "unsupported", kind: "truncated" };
2618
- switch (typeof d) {
2574
+ let c = 0, l = !1;
2575
+ function i(u, d) {
2576
+ if (s !== void 0 && (u = s(d, u)), c += 1, c > t)
2577
+ return l = !0, { [w]: "unsupported", kind: "truncated" };
2578
+ switch (typeof u) {
2619
2579
  case "undefined":
2620
- return { [E]: "undefined" };
2580
+ return { [w]: "undefined" };
2621
2581
  case "bigint":
2622
- return { [E]: "bigint", value: d.toString() };
2582
+ return { [w]: "bigint", value: u.toString() };
2623
2583
  case "number":
2624
- return Number.isNaN(d) ? { [E]: "nan" } : d === 1 / 0 ? { [E]: "infinity", sign: 1 } : d === -1 / 0 ? { [E]: "infinity", sign: -1 } : d;
2584
+ return Number.isNaN(u) ? { [w]: "nan" } : u === 1 / 0 ? { [w]: "infinity", sign: 1 } : u === -1 / 0 ? { [w]: "infinity", sign: -1 } : u;
2625
2585
  case "function":
2626
2586
  case "symbol":
2627
- return n.push(u), { [E]: "unsupported", kind: typeof d };
2587
+ return n.push(d), { [w]: "unsupported", kind: typeof u };
2628
2588
  case "string":
2629
2589
  case "boolean":
2630
- return d;
2590
+ return u;
2631
2591
  }
2632
- if (d === null) return null;
2633
- const f = d, m = r.get(f);
2634
- if (m !== void 0) return { [E]: "ref", path: m };
2635
- if (r.set(f, u), d instanceof Date)
2636
- return { [E]: "date", iso: d.toISOString() };
2637
- if (d instanceof RegExp)
2638
- return { [E]: "regexp", source: d.source, flags: d.flags };
2639
- if (d instanceof Error)
2640
- return { [E]: "error", name: d.name, message: d.message };
2641
- if (d instanceof Map) {
2642
- const y = [];
2643
- let g = 0;
2644
- for (const [w, k] of d)
2645
- y.push([i(w, `${u}/@k${g}`), i(k, `${u}/${g}`)]), g += 1;
2646
- return { [E]: "map", entries: y };
2592
+ if (u === null) return null;
2593
+ const h = u, p = r.get(h);
2594
+ if (p !== void 0) return { [w]: "ref", path: p };
2595
+ if (r.set(h, d), u instanceof Date)
2596
+ return { [w]: "date", iso: u.toISOString() };
2597
+ if (u instanceof RegExp)
2598
+ return { [w]: "regexp", source: u.source, flags: u.flags };
2599
+ if (u instanceof Error)
2600
+ return { [w]: "error", name: u.name, message: u.message };
2601
+ if (u instanceof Map) {
2602
+ const m = [];
2603
+ let y = 0;
2604
+ for (const [g, $] of u)
2605
+ m.push([i(g, `${d}/@k${y}`), i($, `${d}/${y}`)]), y += 1;
2606
+ return { [w]: "map", entries: m };
2647
2607
  }
2648
- if (d instanceof Set) {
2649
- const y = [];
2650
- let g = 0;
2651
- for (const w of d)
2652
- y.push(i(w, `${u}/${g}`)), g += 1;
2653
- return { [E]: "set", values: y };
2608
+ if (u instanceof Set) {
2609
+ const m = [];
2610
+ let y = 0;
2611
+ for (const g of u)
2612
+ m.push(i(g, `${d}/${y}`)), y += 1;
2613
+ return { [w]: "set", values: m };
2654
2614
  }
2655
- if (Array.isArray(d))
2656
- return d.map((y, g) => i(y, `${u}/${g}`));
2657
- const h = {};
2658
- for (const [y, g] of Object.entries(d))
2659
- h[y] = i(g, `${u}/${H(y)}`);
2660
- return E in h ? { [E]: "escaped", value: h } : h;
2661
- }
2662
- return { value: i(c, ""), report: { truncated: l, unsupported: n } };
2615
+ if (Array.isArray(u))
2616
+ return u.map((m, y) => i(m, `${d}/${y}`));
2617
+ const f = {};
2618
+ for (const [m, y] of Object.entries(u))
2619
+ f[m] = i(y, `${d}/${F(m)}`);
2620
+ return w in f ? { [w]: "escaped", value: f } : f;
2621
+ }
2622
+ return { value: i(o, ""), report: { truncated: l, unsupported: n } };
2663
2623
  }
2664
- function oe(c) {
2624
+ function ue(o) {
2665
2625
  const e = /* @__PURE__ */ new Map(), t = [];
2666
- function s(o, l) {
2667
- if (o === null || typeof o != "object") return o;
2668
- if (Array.isArray(o)) {
2626
+ function s(c, l) {
2627
+ if (c === null || typeof c != "object") return c;
2628
+ if (Array.isArray(c)) {
2669
2629
  const a = [];
2670
- return e.set(l, a), o.forEach((d, u) => {
2671
- if (j(d)) {
2672
- t.push({ target: a, key: u, path: d.path }), a[u] = void 0;
2630
+ return e.set(l, a), c.forEach((u, d) => {
2631
+ if (N(u)) {
2632
+ t.push({ target: a, key: d, path: u.path }), a[d] = void 0;
2673
2633
  return;
2674
2634
  }
2675
- a[u] = s(d, `${l}/${u}`);
2635
+ a[d] = s(u, `${l}/${d}`);
2676
2636
  }), a;
2677
2637
  }
2678
- if (typeof o[E] == "string") {
2679
- const a = o;
2680
- switch (a[E]) {
2638
+ if (typeof c[w] == "string") {
2639
+ const a = c;
2640
+ switch (a[w]) {
2681
2641
  case "undefined":
2682
2642
  return;
2683
2643
  case "nan":
@@ -2691,22 +2651,22 @@ function oe(c) {
2691
2651
  case "regexp":
2692
2652
  return new RegExp(a.source, a.flags);
2693
2653
  case "error": {
2694
- const d = new Error(a.message);
2695
- return d.name = a.name, d;
2654
+ const u = new Error(a.message);
2655
+ return u.name = a.name, u;
2696
2656
  }
2697
2657
  case "unsupported":
2698
2658
  return;
2699
2659
  case "ref":
2700
2660
  return;
2701
2661
  case "map": {
2702
- const d = /* @__PURE__ */ new Map();
2703
- return e.set(l, d), a.entries.forEach(([u, f], m) => {
2704
- d.set(s(u, `${l}/@k${m}`), s(f, `${l}/${m}`));
2705
- }), d;
2662
+ const u = /* @__PURE__ */ new Map();
2663
+ return e.set(l, u), a.entries.forEach(([d, h], p) => {
2664
+ u.set(s(d, `${l}/@k${p}`), s(h, `${l}/${p}`));
2665
+ }), u;
2706
2666
  }
2707
2667
  case "set": {
2708
- const d = /* @__PURE__ */ new Set();
2709
- return e.set(l, d), a.values.forEach((u, f) => d.add(s(u, `${l}/${f}`))), d;
2668
+ const u = /* @__PURE__ */ new Set();
2669
+ return e.set(l, u), a.values.forEach((d, h) => u.add(s(d, `${l}/${h}`))), u;
2710
2670
  }
2711
2671
  case "escaped":
2712
2672
  return n(a.value, l);
@@ -2714,37 +2674,37 @@ function oe(c) {
2714
2674
  return;
2715
2675
  }
2716
2676
  }
2717
- return n(o, l);
2677
+ return n(c, l);
2718
2678
  }
2719
- function n(o, l) {
2679
+ function n(c, l) {
2720
2680
  const i = {};
2721
2681
  e.set(l, i);
2722
- for (const [a, d] of Object.entries(o)) {
2723
- const u = `${l}/${H(a)}`;
2724
- if (j(d)) {
2725
- t.push({ target: i, key: a, path: d.path }), i[a] = void 0;
2682
+ for (const [a, u] of Object.entries(c)) {
2683
+ const d = `${l}/${F(a)}`;
2684
+ if (N(u)) {
2685
+ t.push({ target: i, key: a, path: u.path }), i[a] = void 0;
2726
2686
  continue;
2727
2687
  }
2728
- i[a] = s(d, u);
2688
+ i[a] = s(u, d);
2729
2689
  }
2730
2690
  return i;
2731
2691
  }
2732
- const r = s(c, "");
2692
+ const r = s(o, "");
2733
2693
  e.set("", r);
2734
- for (const { target: o, key: l, path: i } of t)
2735
- o[l] = e.get(i);
2694
+ for (const { target: c, key: l, path: i } of t)
2695
+ c[l] = e.get(i);
2736
2696
  return r;
2737
2697
  }
2738
- function j(c) {
2739
- return c !== null && typeof c == "object" && c[E] === "ref" && typeof c.path == "string";
2698
+ function N(o) {
2699
+ return o !== null && typeof o == "object" && o[w] === "ref" && typeof o.path == "string";
2740
2700
  }
2741
- function H(c) {
2742
- return c.replace(/~/g, "~0").replace(/\//g, "~1");
2701
+ function F(o) {
2702
+ return o.replace(/~/g, "~0").replace(/\//g, "~1");
2743
2703
  }
2744
- function pe(c, e, t = {}) {
2704
+ function ge(o, e, t = {}) {
2745
2705
  let s = t.maxNodes ?? 1e5;
2746
2706
  for (let n = 0; n < 8; n += 1) {
2747
- const { value: r, report: o } = B(c, { ...t, maxNodes: s });
2707
+ const { value: r, report: c } = H(o, { ...t, maxNodes: s });
2748
2708
  let l;
2749
2709
  try {
2750
2710
  l = JSON.stringify(r)?.length ?? 0;
@@ -2752,7 +2712,7 @@ function pe(c, e, t = {}) {
2752
2712
  l = Number.POSITIVE_INFINITY;
2753
2713
  }
2754
2714
  if (l <= e)
2755
- return o.truncated ? {
2715
+ return c.truncated ? {
2756
2716
  value: r,
2757
2717
  truncated: !0,
2758
2718
  note: `State was too large to send in full; parts beyond ${s} nodes are omitted.`
@@ -2762,108 +2722,108 @@ function pe(c, e, t = {}) {
2762
2722
  break;
2763
2723
  }
2764
2724
  return {
2765
- value: { [E]: "unsupported", kind: "truncated" },
2725
+ value: { [w]: "unsupported", kind: "truncated" },
2766
2726
  truncated: !0,
2767
2727
  note: `State exceeds the ${e}-byte transport limit and could not be reduced to fit.`
2768
2728
  };
2769
2729
  }
2770
- function v(c, e, t) {
2771
- c.onError?.(e, t);
2730
+ function b(o, e, t) {
2731
+ o.onError?.(e, t);
2772
2732
  }
2773
- async function me(c) {
2733
+ async function we(o) {
2774
2734
  const e = { slices: {}, restored: !1 };
2775
2735
  let t;
2776
2736
  try {
2777
- t = c.source ?? await c.adapter.read(c.key);
2737
+ t = o.source ?? await o.adapter.read(o.key);
2778
2738
  } catch (n) {
2779
- return v(c, n, "read"), e;
2739
+ return b(o, n, "read"), e;
2780
2740
  }
2781
2741
  if (t == null || t === "") return e;
2782
2742
  let s;
2783
2743
  try {
2784
- s = oe(JSON.parse(t));
2744
+ s = ue(JSON.parse(t));
2785
2745
  } catch (n) {
2786
- return v(c, n, "decode"), e;
2746
+ return b(o, n, "decode"), e;
2787
2747
  }
2788
2748
  if (s === null || typeof s != "object" || typeof s.version != "number")
2789
- return v(c, new Error("persisted payload is not a recognisable envelope"), "decode"), e;
2790
- if (s.version !== c.version) {
2791
- if (c.migrate === void 0)
2792
- return v(
2793
- c,
2749
+ return b(o, new Error("persisted payload is not a recognisable envelope"), "decode"), e;
2750
+ if (s.version !== o.version) {
2751
+ if (o.migrate === void 0)
2752
+ return b(
2753
+ o,
2794
2754
  new Error(
2795
- `persisted state is version ${s.version}, this build expects ${c.version}, and no migrate was supplied`
2755
+ `persisted state is version ${s.version}, this build expects ${o.version}, and no migrate was supplied`
2796
2756
  ),
2797
2757
  "migrate"
2798
2758
  ), e;
2799
2759
  try {
2800
- const n = c.migrate(s.slices, s.version);
2760
+ const n = o.migrate(s.slices, s.version);
2801
2761
  return n === null ? e : { slices: n, restored: !0 };
2802
2762
  } catch (n) {
2803
- return v(c, n, "migrate"), e;
2763
+ return b(o, n, "migrate"), e;
2804
2764
  }
2805
2765
  }
2806
2766
  return { slices: s.slices ?? {}, restored: !0 };
2807
2767
  }
2808
- function ye(c, e) {
2809
- if (!e.restored) return c;
2768
+ function Ee(o, e) {
2769
+ if (!e.restored) return o;
2810
2770
  const t = {};
2811
- for (const [s, n] of Object.entries(c)) {
2771
+ for (const [s, n] of Object.entries(o)) {
2812
2772
  const r = e.slices[s];
2813
2773
  t[s] = r === void 0 ? n : { ...n, state: r };
2814
2774
  }
2815
2775
  return t;
2816
2776
  }
2817
- function W(c, e) {
2818
- const t = c ?? {}, s = e.slices === void 0 ? t : Object.fromEntries(e.slices.filter((n) => n in t).map((n) => [n, t[n]]));
2819
- return JSON.stringify(B({ version: e.version, slices: s }).value);
2777
+ function K(o, e) {
2778
+ const t = o ?? {}, s = e.slices === void 0 ? t : Object.fromEntries(e.slices.filter((n) => n in t).map((n) => [n, t[n]]));
2779
+ return JSON.stringify(H({ version: e.version, slices: s }).value);
2820
2780
  }
2821
- function ge(c, e) {
2781
+ function be(o, e) {
2822
2782
  const t = e.throttleMs ?? 250, s = e.slices;
2823
2783
  let n = null, r = !1;
2824
- const o = () => {
2784
+ const c = () => {
2825
2785
  if (r) {
2826
2786
  r = !1;
2827
2787
  try {
2828
- const a = e.adapter.write(e.key, W(c.getState(), e));
2829
- a instanceof Promise && a.catch((d) => v(e, d, "write"));
2788
+ const a = e.adapter.write(e.key, K(o.getState(), e));
2789
+ a instanceof Promise && a.catch((u) => b(e, u, "write"));
2830
2790
  } catch (a) {
2831
- v(e, a, "write");
2791
+ b(e, a, "write");
2832
2792
  }
2833
2793
  }
2834
2794
  }, l = () => {
2835
2795
  if (r = !0, t <= 0) {
2836
- o();
2796
+ c();
2837
2797
  return;
2838
2798
  }
2839
2799
  n === null && (n = setTimeout(() => {
2840
- n = null, o();
2800
+ n = null, c();
2841
2801
  }, t), n.unref?.());
2842
- }, i = c.instrument((a) => {
2802
+ }, i = o.instrument((a) => {
2843
2803
  if (s === void 0) {
2844
2804
  l();
2845
2805
  return;
2846
2806
  }
2847
2807
  (a.changedPaths ?? []).some(
2848
- (u) => s.some((f) => u === f || u.startsWith(`${f}.`))
2808
+ (d) => s.some((h) => d === h || d.startsWith(`${h}.`))
2849
2809
  ) && l();
2850
2810
  });
2851
2811
  return () => {
2852
- i(), n !== null && (clearTimeout(n), n = null), o();
2812
+ i(), n !== null && (clearTimeout(n), n = null), c();
2853
2813
  };
2854
2814
  }
2855
- function we(c, e) {
2856
- return W(c.getState(), e);
2815
+ function ve(o, e) {
2816
+ return K(o.getState(), e);
2857
2817
  }
2858
- function Ee(c) {
2818
+ function Se(o) {
2859
2819
  return {
2860
- read: (e) => c.getItem(e),
2861
- write: (e, t) => c.setItem(e, t),
2862
- remove: (e) => c.removeItem(e)
2820
+ read: (e) => o.getItem(e),
2821
+ write: (e, t) => o.setItem(e, t),
2822
+ remove: (e) => o.removeItem(e)
2863
2823
  };
2864
2824
  }
2865
- function be(c) {
2866
- const e = new Map(Object.entries(c ?? {}));
2825
+ function $e(o) {
2826
+ const e = new Map(Object.entries(o ?? {}));
2867
2827
  return {
2868
2828
  read: (t) => e.get(t) ?? null,
2869
2829
  write: (t, s) => {
@@ -2876,27 +2836,27 @@ function be(c) {
2876
2836
  }
2877
2837
  export {
2878
2838
  C as CallAbortedError,
2879
- J as CallTimeoutError,
2880
- U as EventBus,
2881
- L as LooseEventBus,
2882
- V as Reducer,
2883
- le as Rejected,
2839
+ Q as CallTimeoutError,
2840
+ W as EventBus,
2841
+ U as LooseEventBus,
2842
+ L as Reducer,
2843
+ fe as Rejected,
2884
2844
  x as Store,
2885
- he as createEntityAdapter,
2886
- be as createMemoryAdapter,
2887
- de as createStore,
2888
- Ee as createWebStorageAdapter,
2889
- oe as decodeState,
2890
- we as dehydrate,
2845
+ ye as createEntityAdapter,
2846
+ $e as createMemoryAdapter,
2847
+ he as createStore,
2848
+ Se as createWebStorageAdapter,
2849
+ ue as decodeState,
2850
+ ve as dehydrate,
2891
2851
  I as detectChangedProps,
2892
- B as encodeState,
2893
- pe as encodeStateBounded,
2894
- fe as eventKeys,
2852
+ H as encodeState,
2853
+ ge as encodeStateBounded,
2854
+ me as eventKeys,
2895
2855
  M as freezeState,
2896
- me as hydrate,
2897
- Q as isRejected,
2898
- ge as persist,
2899
- ue as typedEvents,
2900
- ye as withHydration
2856
+ we as hydrate,
2857
+ V as isRejected,
2858
+ be as persist,
2859
+ pe as typedEvents,
2860
+ Ee as withHydration
2901
2861
  };
2902
2862
  //# sourceMappingURL=yoltra.mjs.map