@yoltra/core 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @yoltra/core v0.4.0
2
+ * @yoltra/core v0.5.0
3
3
  * (c) 2026 Manu Ramirez <@pixerael>
4
4
  * License: MIT
5
5
  * Homepage: https://yoltra.dev
@@ -536,10 +536,10 @@ class K {
536
536
  return this._reduce(e, t);
537
537
  }
538
538
  }
539
- const P = /* @__PURE__ */ new Set();
539
+ const k = /* @__PURE__ */ new Set();
540
540
  function M(o, e) {
541
541
  const t = o ? `${o}.${e}` : e;
542
- P.has(t) || (P.add(t), console.warn(
542
+ k.has(t) || (k.add(t), console.warn(
543
543
  `[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
544
  ));
545
545
  }
@@ -653,7 +653,7 @@ function W(o, e) {
653
653
  );
654
654
  }
655
655
  }
656
- function k(o, e) {
656
+ function P(o, e) {
657
657
  return process.env.NODE_ENV === "production" ? o : S(o, /* @__PURE__ */ new WeakSet(), e);
658
658
  }
659
659
  const x = 100, z = () => typeof performance < "u" && typeof performance.now == "function" ? performance.now() : Date.now();
@@ -898,7 +898,7 @@ class $ {
898
898
  * @public
899
899
  */
900
900
  dispose() {
901
- this.eventCleanupTimer && (clearInterval(this.eventCleanupTimer), this.eventCleanupTimer = null), this.processedEvents.clear(), this.effects.clear(), this.patternEffects.clear(), this.effectMeta = /* @__PURE__ */ new WeakMap(), this.listeners.clear(), this.committedEventSubscribers.clear(), this.uncommittedEventSubscribers.clear(), this.allEventSubscribers.clear(), this.instrumentObservers.clear(), this.connectorBus.clear(), this.reducerBus.clear(), this.patternReducers.clear(), this.sliceUnsubs.clear(), this.changedPathSink = null;
901
+ this.eventCleanupTimer && (clearInterval(this.eventCleanupTimer), this.eventCleanupTimer = null), this.processedEvents.clear(), this.effects.clear(), this.patternEffects.clear(), this.effectMeta = /* @__PURE__ */ new WeakMap(), this.warnedPayloadAliases.clear(), this.listeners.clear(), this.committedEventSubscribers.clear(), this.uncommittedEventSubscribers.clear(), this.allEventSubscribers.clear(), this.instrumentObservers.clear(), this.connectorBus.clear(), this.reducerBus.clear(), this.patternReducers.clear(), this.sliceUnsubs.clear(), this.changedPathSink = null;
902
902
  }
903
903
  /**
904
904
  * Generates a fingerprint for an event for deduplication purposes.
@@ -1071,6 +1071,11 @@ class $ {
1071
1071
  * For each changed **leaf path** (via {@link detectChangedProps}), emits that leaf and
1072
1072
  * all of its **ancestors** once (e.g., `"data"`, `"data.123"`, `"data.123.title"`).
1073
1073
  *
1074
+ * A slice whose state **is** a single value — a primitive, a `Map`/`Set`, a `Date` — has no
1075
+ * leaf below its root, and `detectChangedProps` reports its change as the empty path `""`.
1076
+ * That path is emitted as-is, so `connect({ reducer, property: "" })` (and any `**` pattern)
1077
+ * hears it. It has no ancestors to walk.
1078
+ *
1074
1079
  * **State Immutability**: When a slice changes, a new state object is created via
1075
1080
  * shallow spread: `{ ...this.state, [sliceName]: newSlice }`. This ensures that
1076
1081
  * `this.state` reference changes, enabling efficient change detection via `===`.
@@ -1114,7 +1119,7 @@ class $ {
1114
1119
  forwardEvent(e, t) {
1115
1120
  const n = this.state[e], s = this.reducers[e].reduce(n, t);
1116
1121
  if (n === s) return !1;
1117
- const i = O(n, s).filter(Boolean);
1122
+ const i = O(n, s);
1118
1123
  if (i.length === 0) return !1;
1119
1124
  const d = t.payload, a = process.env.NODE_ENV !== "production" && d !== null && typeof d == "object" ? {
1120
1125
  watch: d,
@@ -1124,13 +1129,18 @@ class $ {
1124
1129
  `[yoltra] Slice "${e}" stored the payload of "${t.channel}/${t.type}" by reference. It is now frozen along with the rest of the state, so the emitter mutating it later will throw in development and silently corrupt state in production. Copy the payload in the reducer instead.`
1125
1130
  ));
1126
1131
  }
1127
- } : void 0, r = k(s, a);
1132
+ } : void 0, r = P(s, a);
1128
1133
  if (this.state = { ...this.state, [e]: r }, this.changedPathSink)
1129
1134
  for (const c of i)
1130
1135
  this.changedPathSink.push(c ? `${e}.${c}` : e);
1131
1136
  const f = /* @__PURE__ */ new Set();
1132
- for (const c of i)
1137
+ for (const c of i) {
1138
+ if (c === "") {
1139
+ f.add("");
1140
+ continue;
1141
+ }
1133
1142
  for (const u of $.buildAncestorPaths(c)) f.add(u);
1143
+ }
1134
1144
  for (const c of f)
1135
1145
  this.connectorBus.emitWith(e, c, () => ({
1136
1146
  oldValue: this.getAtPath(n, c),
@@ -1246,12 +1256,18 @@ class $ {
1246
1256
  return;
1247
1257
  }
1248
1258
  if (a === r) return;
1249
- const f = k(r);
1259
+ const f = P(r);
1250
1260
  s[d] = f, i = !0;
1251
- const c = O(a, r).filter(Boolean);
1261
+ const c = O(a, r);
1252
1262
  if (c.length === 0) return;
1253
1263
  const u = /* @__PURE__ */ new Set();
1254
- for (const l of c) for (const y of $.buildAncestorPaths(l)) u.add(y);
1264
+ for (const l of c) {
1265
+ if (l === "") {
1266
+ u.add("");
1267
+ continue;
1268
+ }
1269
+ for (const y of $.buildAncestorPaths(l)) u.add(y);
1270
+ }
1255
1271
  for (const l of u) {
1256
1272
  const y = this.getAtPath(a, l), h = this.getAtPath(f, l);
1257
1273
  this.connectorBus.emit(d, l, { oldValue: y, newValue: h, path: l });
@@ -1678,7 +1694,8 @@ class $ {
1678
1694
  * @public
1679
1695
  */
1680
1696
  registerReducer(e, t) {
1681
- if (e in this.reducers) throw new Error(`Reducer ${e} already exists`);
1697
+ if (Object.prototype.hasOwnProperty.call(this.reducers, e))
1698
+ throw new Error(`Reducer ${e} already exists`);
1682
1699
  return this.mountSlice(e, t, {
1683
1700
  preserveState: !1
1684
1701
  }), this.listeners.forEach((n) => n()), () => {
@@ -1874,7 +1891,7 @@ class $ {
1874
1891
  const s = e, { reducer: i, state: d, when: a } = t;
1875
1892
  if (this.reducers[e] = new K(i), (!n.preserveState || this.state[s] === void 0) && (this.state = {
1876
1893
  ...this.state,
1877
- [s]: k(W(s, d))
1894
+ [s]: P(W(s, d))
1878
1895
  }), a && ("any" in a && a.any === !0 || "channel" in a || "channels" in a)) {
1879
1896
  this.patternReducers.set(e, a), this.sliceUnsubs.set(s, []);
1880
1897
  return;
@@ -2132,7 +2149,7 @@ function _(o, e = {}) {
2132
2149
  return c.map((m, g) => r(m, `${u}/${g}`));
2133
2150
  const h = {};
2134
2151
  for (const [m, g] of Object.entries(c))
2135
- h[m] = r(g, `${u}/${N(m)}`);
2152
+ h[m] = r(g, `${u}/${A(m)}`);
2136
2153
  return E in h ? { [E]: "escaped", value: h } : h;
2137
2154
  }
2138
2155
  return { value: r(o, ""), report: { truncated: a, unsupported: s } };
@@ -2196,7 +2213,7 @@ function V(o) {
2196
2213
  const r = {};
2197
2214
  e.set(a, r);
2198
2215
  for (const [f, c] of Object.entries(d)) {
2199
- const u = `${a}/${N(f)}`;
2216
+ const u = `${a}/${A(f)}`;
2200
2217
  if (R(c)) {
2201
2218
  t.push({ target: r, key: f, path: c.path }), r[f] = void 0;
2202
2219
  continue;
@@ -2214,7 +2231,7 @@ function V(o) {
2214
2231
  function R(o) {
2215
2232
  return o !== null && typeof o == "object" && o[E] === "ref" && typeof o.path == "string";
2216
2233
  }
2217
- function N(o) {
2234
+ function A(o) {
2218
2235
  return o.replace(/~/g, "~0").replace(/\//g, "~1");
2219
2236
  }
2220
2237
  function Y(o, e, t = {}) {
@@ -2290,7 +2307,7 @@ function X(o, e) {
2290
2307
  }
2291
2308
  return t;
2292
2309
  }
2293
- function A(o, e) {
2310
+ function N(o, e) {
2294
2311
  const t = o ?? {}, n = e.slices === void 0 ? t : Object.fromEntries(e.slices.filter((s) => s in t).map((s) => [s, t[s]]));
2295
2312
  return JSON.stringify(_({ version: e.version, slices: n }).value);
2296
2313
  }
@@ -2301,7 +2318,7 @@ function Z(o, e) {
2301
2318
  if (i) {
2302
2319
  i = !1;
2303
2320
  try {
2304
- const f = e.adapter.write(e.key, A(o.getState(), e));
2321
+ const f = e.adapter.write(e.key, N(o.getState(), e));
2305
2322
  f instanceof Promise && f.catch((c) => b(e, c, "write"));
2306
2323
  } catch (f) {
2307
2324
  b(e, f, "write");
@@ -2329,7 +2346,7 @@ function Z(o, e) {
2329
2346
  };
2330
2347
  }
2331
2348
  function ee(o, e) {
2332
- return A(o.getState(), e);
2349
+ return N(o.getState(), e);
2333
2350
  }
2334
2351
  function te(o) {
2335
2352
  return {
@@ -2371,4 +2388,4 @@ export {
2371
2388
  G as typedEvents,
2372
2389
  X as withHydration
2373
2390
  };
2374
- //# sourceMappingURL=yoltra.esm.js.map
2391
+ //# sourceMappingURL=yoltra.mjs.map