mvc-kit 2.3.0 → 2.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.
Files changed (42) hide show
  1. package/README.md +83 -2
  2. package/agent-config/claude-code/agents/mvc-kit-architect.md +7 -5
  3. package/agent-config/claude-code/skills/guide/anti-patterns.md +114 -1
  4. package/agent-config/claude-code/skills/guide/api-reference.md +74 -2
  5. package/agent-config/claude-code/skills/guide/patterns.md +65 -0
  6. package/agent-config/copilot/copilot-instructions.md +7 -2
  7. package/agent-config/cursor/cursorrules +7 -2
  8. package/dist/PersistentCollection-B8kNECDj.cjs +2 -0
  9. package/dist/PersistentCollection-B8kNECDj.cjs.map +1 -0
  10. package/dist/PersistentCollection-BFrgskju.js +542 -0
  11. package/dist/PersistentCollection-BFrgskju.js.map +1 -0
  12. package/dist/PersistentCollection.d.ts +69 -0
  13. package/dist/PersistentCollection.d.ts.map +1 -0
  14. package/dist/Resource.d.ts +60 -0
  15. package/dist/Resource.d.ts.map +1 -0
  16. package/dist/index.d.ts +3 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/mvc-kit.cjs +1 -1
  19. package/dist/mvc-kit.cjs.map +1 -1
  20. package/dist/mvc-kit.js +328 -442
  21. package/dist/mvc-kit.js.map +1 -1
  22. package/dist/react-native/NativeCollection.d.ts +65 -0
  23. package/dist/react-native/NativeCollection.d.ts.map +1 -0
  24. package/dist/react-native/index.d.ts +2 -0
  25. package/dist/react-native/index.d.ts.map +1 -0
  26. package/dist/react-native.cjs +2 -0
  27. package/dist/react-native.cjs.map +1 -0
  28. package/dist/react-native.js +63 -0
  29. package/dist/react-native.js.map +1 -0
  30. package/dist/web/IndexedDBCollection.d.ts +37 -0
  31. package/dist/web/IndexedDBCollection.d.ts.map +1 -0
  32. package/dist/web/WebStorageCollection.d.ts +33 -0
  33. package/dist/web/WebStorageCollection.d.ts.map +1 -0
  34. package/dist/web/idb.d.ts +16 -0
  35. package/dist/web/idb.d.ts.map +1 -0
  36. package/dist/web/index.d.ts +3 -0
  37. package/dist/web/index.d.ts.map +1 -0
  38. package/dist/web.cjs +2 -0
  39. package/dist/web.cjs.map +1 -0
  40. package/dist/web.js +181 -0
  41. package/dist/web.js.map +1 -0
  42. package/package.json +22 -1
package/dist/mvc-kit.js CHANGED
@@ -1,31 +1,33 @@
1
- import { E as w } from "./singleton-CaEXSbYg.js";
2
- import { h as N, s as $, t as L, a as B } from "./singleton-CaEXSbYg.js";
3
- class C extends Error {
1
+ import { E } from "./singleton-CaEXSbYg.js";
2
+ import { h as B, s as F, t as X, a as Y } from "./singleton-CaEXSbYg.js";
3
+ import { C as A } from "./PersistentCollection-BFrgskju.js";
4
+ import { P as U } from "./PersistentCollection-BFrgskju.js";
5
+ class x extends Error {
4
6
  constructor(t, s) {
5
7
  super(s ?? `HTTP ${t}`), this.status = t, this.name = "HttpError";
6
8
  }
7
9
  }
8
- function y(r) {
10
+ function O(r) {
9
11
  return r instanceof Error && r.name === "AbortError";
10
12
  }
11
- function S(r) {
13
+ function C(r) {
12
14
  return r === 401 ? "unauthorized" : r === 403 ? "forbidden" : r === 404 ? "not_found" : r === 422 ? "validation" : r === 429 ? "rate_limited" : r >= 500 ? "server_error" : "unknown";
13
15
  }
14
- function T(r) {
16
+ function z(r) {
15
17
  return typeof r == "object" && r !== null && typeof r.status == "number" && typeof r.statusText == "string" && !(r instanceof Error);
16
18
  }
17
- function E(r) {
19
+ function T(r) {
18
20
  return r instanceof Error && r.name === "AbortError" ? {
19
21
  code: "abort",
20
22
  message: "Request was aborted",
21
23
  original: r
22
- } : r instanceof C ? {
23
- code: S(r.status),
24
+ } : r instanceof x ? {
25
+ code: C(r.status),
24
26
  message: r.message,
25
27
  status: r.status,
26
28
  original: r
27
- } : T(r) ? {
28
- code: S(r.status),
29
+ } : z(r) ? {
30
+ code: C(r.status),
29
31
  message: r.statusText || `HTTP ${r.status}`,
30
32
  status: r.status,
31
33
  original: r
@@ -48,20 +50,20 @@ function E(r) {
48
50
  };
49
51
  }
50
52
  const d = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__;
51
- function O(r) {
53
+ function M(r) {
52
54
  return r !== null && typeof r == "object" && typeof r.subscribe == "function";
53
55
  }
54
56
  function b(r, t, s) {
55
57
  let e = Object.getPrototypeOf(r);
56
58
  for (; e && e !== t; ) {
57
- const i = Object.getOwnPropertyDescriptors(e);
58
- for (const [n, a] of Object.entries(i))
59
- n !== "constructor" && s(n, a, e);
59
+ const n = Object.getOwnPropertyDescriptors(e);
60
+ for (const [o, c] of Object.entries(n))
61
+ o !== "constructor" && s(o, c, e);
60
62
  e = Object.getPrototypeOf(e);
61
63
  }
62
64
  }
63
- const z = Object.freeze({ loading: !1, error: null, errorCode: null }), v = ["async", "subscribeAsync"], A = /* @__PURE__ */ new Set(["onInit", "onSet", "onDispose"]);
64
- class m {
65
+ const j = Object.freeze({ loading: !1, error: null, errorCode: null }), m = ["async", "subscribeAsync"], P = /* @__PURE__ */ new Set(["onInit", "onSet", "onDispose"]);
66
+ class S {
65
67
  _state;
66
68
  _initialState;
67
69
  _disposed = !1;
@@ -105,7 +107,7 @@ class m {
105
107
  }
106
108
  /** Lazily-created typed EventBus for emitting and subscribing to events. */
107
109
  get events() {
108
- return this._eventBus || (this._eventBus = new w()), this._eventBus;
110
+ return this._eventBus || (this._eventBus = new E()), this._eventBus;
109
111
  }
110
112
  /** Initializes the instance. Called automatically by React hooks after mount. */
111
113
  init() {
@@ -132,13 +134,13 @@ class m {
132
134
  }
133
135
  const s = typeof t == "function" ? t(this._state) : t;
134
136
  if (!Object.keys(s).some(
135
- (o) => s[o] !== this._state[o]
137
+ (l) => s[l] !== this._state[l]
136
138
  ))
137
139
  return;
138
- const n = this._state, a = Object.freeze({ ...n, ...s });
139
- this._state = a, this._revision++, this.onSet?.(n, a);
140
- for (const o of this._listeners)
141
- o(a, n);
140
+ const o = this._state, c = Object.freeze({ ...o, ...s });
141
+ this._state = c, this._revision++, this.onSet?.(o, c);
142
+ for (const l of this._listeners)
143
+ l(c, o);
142
144
  }
143
145
  /**
144
146
  * Emits a typed event via the internal EventBus.
@@ -198,7 +200,7 @@ class m {
198
200
  const t = this;
199
201
  this._asyncProxy = new Proxy({}, {
200
202
  get(s, e) {
201
- return t._asyncSnapshots.get(e) ?? z;
203
+ return t._asyncSnapshots.get(e) ?? j;
202
204
  },
203
205
  has(s, e) {
204
206
  return t._asyncSnapshots.has(e);
@@ -234,88 +236,88 @@ class m {
234
236
  }
235
237
  }
236
238
  _guardReservedKeys() {
237
- b(this, m.prototype, (t) => {
238
- if (v.includes(t))
239
+ b(this, S.prototype, (t) => {
240
+ if (m.includes(t))
239
241
  throw new Error(
240
242
  `[mvc-kit] "${t}" is a reserved property on ViewModel and cannot be overridden.`
241
243
  );
242
244
  });
243
245
  }
244
246
  _wrapMethods() {
245
- for (const i of v)
246
- if (Object.getOwnPropertyDescriptor(this, i)?.value !== void 0)
247
+ for (const n of m)
248
+ if (Object.getOwnPropertyDescriptor(this, n)?.value !== void 0)
247
249
  throw new Error(
248
- `[mvc-kit] "${i}" is a reserved property on ViewModel and cannot be overridden.`
250
+ `[mvc-kit] "${n}" is a reserved property on ViewModel and cannot be overridden.`
249
251
  );
250
252
  const t = this, s = /* @__PURE__ */ new Set(), e = [];
251
- d && (this._activeOps = /* @__PURE__ */ new Map()), b(this, m.prototype, (i, n) => {
252
- if (n.get || n.set || typeof n.value != "function" || i.startsWith("_") || A.has(i) || s.has(i)) return;
253
- s.add(i);
254
- const a = n.value;
255
- let o = !1;
256
- const l = function(...h) {
253
+ d && (this._activeOps = /* @__PURE__ */ new Map()), b(this, S.prototype, (n, o) => {
254
+ if (o.get || o.set || typeof o.value != "function" || n.startsWith("_") || P.has(n) || s.has(n)) return;
255
+ s.add(n);
256
+ const c = o.value;
257
+ let l = !1;
258
+ const p = function(...g) {
257
259
  if (t._disposed) {
258
- d && console.warn(`[mvc-kit] "${i}" called after dispose — ignored.`);
260
+ d && console.warn(`[mvc-kit] "${n}" called after dispose — ignored.`);
259
261
  return;
260
262
  }
261
263
  d && !t._initialized && console.warn(
262
- `[mvc-kit] "${i}" called before init(). Async tracking is active only after init().`
264
+ `[mvc-kit] "${n}" called before init(). Async tracking is active only after init().`
263
265
  );
264
266
  let u;
265
267
  try {
266
- u = a.apply(t, h);
267
- } catch (_) {
268
- throw _;
268
+ u = c.apply(t, g);
269
+ } catch (a) {
270
+ throw a;
269
271
  }
270
272
  if (!u || typeof u.then != "function")
271
- return o || (o = !0, t._asyncStates.delete(i), t._asyncSnapshots.delete(i), t[i] = a.bind(t)), u;
272
- let c = t._asyncStates.get(i);
273
- return c || (c = { loading: !1, error: null, errorCode: null, count: 0 }, t._asyncStates.set(i, c)), c.count++, c.loading = !0, c.error = null, c.errorCode = null, t._asyncSnapshots.set(i, Object.freeze({ loading: !0, error: null, errorCode: null })), t._notifyAsync(), d && t._activeOps && t._activeOps.set(i, (t._activeOps.get(i) ?? 0) + 1), u.then(
274
- (_) => {
275
- if (t._disposed) return _;
276
- if (c.count--, c.loading = c.count > 0, t._asyncSnapshots.set(
277
- i,
278
- Object.freeze({ loading: c.loading, error: c.error, errorCode: c.errorCode })
273
+ return l || (l = !0, t._asyncStates.delete(n), t._asyncSnapshots.delete(n), t[n] = c.bind(t)), u;
274
+ let i = t._asyncStates.get(n);
275
+ return i || (i = { loading: !1, error: null, errorCode: null, count: 0 }, t._asyncStates.set(n, i)), i.count++, i.loading = !0, i.error = null, i.errorCode = null, t._asyncSnapshots.set(n, Object.freeze({ loading: !0, error: null, errorCode: null })), t._notifyAsync(), d && t._activeOps && t._activeOps.set(n, (t._activeOps.get(n) ?? 0) + 1), u.then(
276
+ (a) => {
277
+ if (t._disposed) return a;
278
+ if (i.count--, i.loading = i.count > 0, t._asyncSnapshots.set(
279
+ n,
280
+ Object.freeze({ loading: i.loading, error: i.error, errorCode: i.errorCode })
279
281
  ), t._notifyAsync(), d && t._activeOps) {
280
- const f = (t._activeOps.get(i) ?? 1) - 1;
281
- f <= 0 ? t._activeOps.delete(i) : t._activeOps.set(i, f);
282
+ const _ = (t._activeOps.get(n) ?? 1) - 1;
283
+ _ <= 0 ? t._activeOps.delete(n) : t._activeOps.set(n, _);
282
284
  }
283
- return _;
285
+ return a;
284
286
  },
285
- (_) => {
286
- if (y(_)) {
287
- if (t._disposed || (c.count--, c.loading = c.count > 0, t._asyncSnapshots.set(
288
- i,
289
- Object.freeze({ loading: c.loading, error: c.error, errorCode: c.errorCode })
287
+ (a) => {
288
+ if (O(a)) {
289
+ if (t._disposed || (i.count--, i.loading = i.count > 0, t._asyncSnapshots.set(
290
+ n,
291
+ Object.freeze({ loading: i.loading, error: i.error, errorCode: i.errorCode })
290
292
  ), t._notifyAsync()), d && t._activeOps) {
291
- const p = (t._activeOps.get(i) ?? 1) - 1;
292
- p <= 0 ? t._activeOps.delete(i) : t._activeOps.set(i, p);
293
+ const h = (t._activeOps.get(n) ?? 1) - 1;
294
+ h <= 0 ? t._activeOps.delete(n) : t._activeOps.set(n, h);
293
295
  }
294
296
  return;
295
297
  }
296
298
  if (t._disposed) return;
297
- c.count--, c.loading = c.count > 0;
298
- const f = E(_);
299
- if (c.error = f.message, c.errorCode = f.code, t._asyncSnapshots.set(
300
- i,
301
- Object.freeze({ loading: c.loading, error: f.message, errorCode: f.code })
299
+ i.count--, i.loading = i.count > 0;
300
+ const _ = T(a);
301
+ if (i.error = _.message, i.errorCode = _.code, t._asyncSnapshots.set(
302
+ n,
303
+ Object.freeze({ loading: i.loading, error: _.message, errorCode: _.code })
302
304
  ), t._notifyAsync(), d && t._activeOps) {
303
- const p = (t._activeOps.get(i) ?? 1) - 1;
304
- p <= 0 ? t._activeOps.delete(i) : t._activeOps.set(i, p);
305
+ const h = (t._activeOps.get(n) ?? 1) - 1;
306
+ h <= 0 ? t._activeOps.delete(n) : t._activeOps.set(n, h);
305
307
  }
306
- throw _;
308
+ throw a;
307
309
  }
308
310
  );
309
311
  };
310
- e.push(i), t[i] = l;
312
+ e.push(n), t[n] = p;
311
313
  }), e.length > 0 && this.addCleanup(() => {
312
- const i = d && t._activeOps ? new Map(t._activeOps) : null;
313
- for (const n of e)
314
- d ? t[n] = () => {
315
- console.warn(`[mvc-kit] "${n}" called after dispose — ignored.`);
316
- } : t[n] = () => {
314
+ const n = d && t._activeOps ? new Map(t._activeOps) : null;
315
+ for (const o of e)
316
+ d ? t[o] = () => {
317
+ console.warn(`[mvc-kit] "${o}" called after dispose — ignored.`);
318
+ } : t[o] = () => {
317
319
  };
318
- t._asyncListeners.clear(), t._asyncStates.clear(), t._asyncSnapshots.clear(), d && i && i.size > 0 && t._scheduleGhostCheck(i);
320
+ t._asyncListeners.clear(), t._asyncStates.clear(), t._asyncSnapshots.clear(), d && n && n.size > 0 && t._scheduleGhostCheck(n);
319
321
  });
320
322
  }
321
323
  _scheduleGhostCheck(t) {
@@ -371,15 +373,15 @@ class m {
371
373
  _trackSubscribables() {
372
374
  for (const t of Object.getOwnPropertyNames(this)) {
373
375
  const s = this[t];
374
- if (!O(s)) continue;
376
+ if (!M(s)) continue;
375
377
  const e = {
376
378
  source: s,
377
379
  revision: 0,
378
380
  unsubscribe: s.subscribe(() => {
379
381
  if (!this._disposed) {
380
382
  e.revision++, this._revision++, this._state = Object.freeze({ ...this._state });
381
- for (const i of this._listeners)
382
- i(this._state, this._state);
383
+ for (const n of this._listeners)
384
+ n(this._state, this._state);
383
385
  }
384
386
  })
385
387
  };
@@ -400,7 +402,7 @@ class m {
400
402
  */
401
403
  _memoizeGetters() {
402
404
  const t = /* @__PURE__ */ new Set();
403
- b(this, m.prototype, (s, e) => {
405
+ b(this, S.prototype, (s, e) => {
404
406
  !e.get || t.has(s) || (t.add(s), this._wrapGetter(s, e.get));
405
407
  });
406
408
  }
@@ -415,57 +417,57 @@ class m {
415
417
  * Tier 3 (slow): at least one dep changed → full recompute with tracking
416
418
  */
417
419
  _wrapGetter(t, s) {
418
- let e, i = -1, n, a, o;
420
+ let e, n = -1, o, c, l;
419
421
  Object.defineProperty(this, t, {
420
422
  get: () => {
421
- if (this._disposed || i === this._revision)
423
+ if (this._disposed || n === this._revision)
422
424
  return e;
423
- if (n && a) {
424
- let c = !0;
425
- for (const [_, f] of a)
426
- if (this._state[_] !== f) {
427
- c = !1;
425
+ if (o && c) {
426
+ let i = !0;
427
+ for (const [a, _] of c)
428
+ if (this._state[a] !== _) {
429
+ i = !1;
428
430
  break;
429
431
  }
430
- if (c && o)
431
- for (const [_, f] of o) {
432
- const p = this._trackedSources.get(_);
433
- if (p && p.revision !== f) {
434
- c = !1;
432
+ if (i && l)
433
+ for (const [a, _] of l) {
434
+ const h = this._trackedSources.get(a);
435
+ if (h && h.revision !== _) {
436
+ i = !1;
435
437
  break;
436
438
  }
437
439
  }
438
- if (c)
439
- return i = this._revision, e;
440
+ if (i)
441
+ return n = this._revision, e;
440
442
  }
441
- const l = this._stateTracking, h = this._sourceTracking;
443
+ const p = this._stateTracking, g = this._sourceTracking;
442
444
  this._stateTracking = /* @__PURE__ */ new Set(), this._sourceTracking = /* @__PURE__ */ new Map();
443
445
  try {
444
446
  e = s.call(this);
445
- } catch (c) {
446
- throw this._stateTracking = l, this._sourceTracking = h, c;
447
+ } catch (i) {
448
+ throw this._stateTracking = p, this._sourceTracking = g, i;
447
449
  }
448
- n = this._stateTracking;
450
+ o = this._stateTracking;
449
451
  const u = this._sourceTracking;
450
- if (this._stateTracking = l, this._sourceTracking = h, l)
451
- for (const c of n) l.add(c);
452
- if (h)
453
- for (const [c, _] of u)
454
- h.set(c, _);
455
- a = /* @__PURE__ */ new Map();
456
- for (const c of n)
457
- a.set(c, this._state[c]);
458
- o = /* @__PURE__ */ new Map();
459
- for (const [c, _] of u)
460
- o.set(c, _.revision);
461
- return i = this._revision, e;
452
+ if (this._stateTracking = p, this._sourceTracking = g, p)
453
+ for (const i of o) p.add(i);
454
+ if (g)
455
+ for (const [i, a] of u)
456
+ g.set(i, a);
457
+ c = /* @__PURE__ */ new Map();
458
+ for (const i of o)
459
+ c.set(i, this._state[i]);
460
+ l = /* @__PURE__ */ new Map();
461
+ for (const [i, a] of u)
462
+ l.set(i, a.revision);
463
+ return n = this._revision, e;
462
464
  },
463
465
  configurable: !0,
464
466
  enumerable: !0
465
467
  });
466
468
  }
467
469
  }
468
- class j {
470
+ class $ {
469
471
  _state;
470
472
  _committed;
471
473
  _disposed = !1;
@@ -531,13 +533,13 @@ class j {
531
533
  throw new Error("Cannot set state on disposed Model");
532
534
  const s = typeof t == "function" ? t(this._state) : t;
533
535
  if (!Object.keys(s).some(
534
- (o) => s[o] !== this._state[o]
536
+ (l) => s[l] !== this._state[l]
535
537
  ))
536
538
  return;
537
- const n = this._state, a = Object.freeze({ ...n, ...s });
538
- this._state = a, this.onSet?.(n, a);
539
- for (const o of this._listeners)
540
- o(a, n);
539
+ const o = this._state, c = Object.freeze({ ...o, ...s });
540
+ this._state = c, this.onSet?.(o, c);
541
+ for (const l of this._listeners)
542
+ l(c, o);
541
543
  }
542
544
  /**
543
545
  * Mark current state as the new baseline (not dirty).
@@ -594,348 +596,230 @@ class j {
594
596
  return this.addCleanup(e), e;
595
597
  }
596
598
  shallowEqual(t, s) {
597
- const e = Object.keys(t), i = Object.keys(s);
598
- if (e.length !== i.length)
599
+ const e = Object.keys(t), n = Object.keys(s);
600
+ if (e.length !== n.length)
599
601
  return !1;
600
- for (const n of e)
601
- if (t[n] !== s[n])
602
+ for (const o of e)
603
+ if (t[o] !== s[o])
602
604
  return !1;
603
605
  return !0;
604
606
  }
605
607
  }
606
- const x = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__;
607
- class D {
608
- /** Maximum number of items before FIFO eviction. 0 = unlimited. */
609
- static MAX_SIZE = 0;
610
- /** Time-to-live in milliseconds. 0 = no expiry. */
611
- static TTL = 0;
612
- _items = [];
613
- _disposed = !1;
614
- _listeners = /* @__PURE__ */ new Set();
615
- _index = /* @__PURE__ */ new Map();
616
- _abortController = null;
617
- _cleanups = null;
618
- _timestamps = null;
619
- _evictionTimer = null;
620
- constructor(t = []) {
621
- let s = [...t];
622
- if (this._ttl > 0) {
623
- this._timestamps = /* @__PURE__ */ new Map();
624
- const e = Date.now();
625
- for (const i of s)
626
- this._timestamps.set(i.id, e);
627
- }
628
- if (this._maxSize > 0 && s.length > this._maxSize) {
629
- const e = s.length - this._maxSize, i = s.slice(0, e);
630
- s = s.slice(e);
631
- for (const n of i)
632
- this._timestamps?.delete(n.id);
608
+ const f = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__, D = Object.freeze({ loading: !1, error: null, errorCode: null }), w = ["async", "subscribeAsync"], k = /* @__PURE__ */ new Set(["onInit", "onDispose"]);
609
+ class v extends A {
610
+ _external = null;
611
+ _initialized = !1;
612
+ // ── Async tracking fields ──
613
+ _asyncStates = /* @__PURE__ */ new Map();
614
+ _asyncSnapshots = /* @__PURE__ */ new Map();
615
+ _asyncListeners = /* @__PURE__ */ new Set();
616
+ _asyncProxy = null;
617
+ _activeOps = null;
618
+ /** DEV-only timeout (ms) for detecting ghost async operations after dispose. */
619
+ static GHOST_TIMEOUT = 3e3;
620
+ constructor(t) {
621
+ const s = t != null && !Array.isArray(t);
622
+ if (super(s ? [] : t ?? []), s && (this._external = t, f)) {
623
+ const e = this.constructor;
624
+ (e.MAX_SIZE > 0 || e.TTL > 0) && console.warn(
625
+ `[mvc-kit] Resource "${e.name}" has MAX_SIZE or TTL set but uses an injected Collection. Configure these on the Collection instead.`
626
+ );
633
627
  }
634
- this._items = Object.freeze(s), this.rebuildIndex(), this._scheduleEvictionTimer();
628
+ this._guardReservedKeys();
635
629
  }
636
- /**
637
- * Alias for Subscribable compatibility.
638
- */
630
+ // ── Lifecycle ─────────────────────────────────────────────────
631
+ /** Whether init() has been called. */
632
+ get initialized() {
633
+ return this._initialized;
634
+ }
635
+ /** Initializes the instance. Called automatically by React hooks after mount. */
636
+ init() {
637
+ if (!(this._initialized || this.disposed))
638
+ return this._initialized = !0, this._wrapMethods(), this.onInit?.();
639
+ }
640
+ // ── Collection delegation ─────────────────────────────────────
639
641
  get state() {
640
- return this._items;
642
+ return this._external ? this._external.state : super.state;
641
643
  }
642
- /** The raw readonly array of items. */
643
644
  get items() {
644
- return this._items;
645
+ return this._external ? this._external.items : super.items;
645
646
  }
646
- /** Number of items in the collection. */
647
647
  get length() {
648
- return this._items.length;
649
- }
650
- /** Whether this instance has been disposed. */
651
- get disposed() {
652
- return this._disposed;
648
+ return this._external ? this._external.length : super.length;
653
649
  }
654
- /** AbortSignal that fires when this instance is disposed. Lazily created. */
655
- get disposeSignal() {
656
- return this._abortController || (this._abortController = new AbortController()), this._abortController.signal;
657
- }
658
- // ── Config Accessors ──
659
- get _maxSize() {
660
- return this.constructor.MAX_SIZE;
661
- }
662
- get _ttl() {
663
- return this.constructor.TTL;
664
- }
665
- // ── CRUD Methods (notify listeners) ──
666
- /**
667
- * Add one or more items. Items with existing IDs are silently skipped.
668
- */
669
650
  add(...t) {
670
- if (this._disposed)
671
- throw new Error("Cannot add to disposed Collection");
672
- if (t.length === 0)
673
- return;
674
- const s = /* @__PURE__ */ new Set(), e = [];
675
- for (const a of t)
676
- !this._index.has(a.id) && !s.has(a.id) && (e.push(a), s.add(a.id));
677
- if (e.length === 0) return;
678
- const i = this._items;
679
- let n = [...i, ...e];
680
- for (const a of e)
681
- this._index.set(a.id, a);
682
- if (this._timestamps) {
683
- const a = Date.now();
684
- for (const o of e)
685
- this._timestamps.set(o.id, a);
686
- }
687
- this._maxSize > 0 && n.length > this._maxSize && (n = this._evictForCapacity(n)), this._items = Object.freeze(n), this.notify(i), this._scheduleEvictionTimer();
651
+ this._external ? this._external.add(...t) : super.add(...t);
688
652
  }
689
- /**
690
- * Add or replace items by ID. Existing items are replaced in-place
691
- * (preserving array position); new items are appended. Deduplicates
692
- * input — last occurrence wins. No-op if nothing changed (reference
693
- * comparison).
694
- */
695
653
  upsert(...t) {
696
- if (this._disposed)
697
- throw new Error("Cannot upsert on disposed Collection");
698
- if (t.length === 0) return;
699
- const s = /* @__PURE__ */ new Map();
700
- for (const l of t)
701
- s.set(l.id, l);
702
- const e = this._items;
703
- let i = !1;
704
- const n = /* @__PURE__ */ new Set(), a = [];
705
- for (const l of e)
706
- if (s.has(l.id)) {
707
- const h = s.get(l.id);
708
- h !== l && (i = !0), a.push(h), n.add(l.id);
709
- } else
710
- a.push(l);
711
- for (const [l, h] of s)
712
- n.has(l) || (a.push(h), i = !0);
713
- if (!i) return;
714
- if (this._timestamps) {
715
- const l = Date.now();
716
- for (const [h] of s)
717
- this._timestamps.set(h, l);
718
- }
719
- for (const [l, h] of s)
720
- this._index.set(l, h);
721
- let o = a;
722
- this._maxSize > 0 && o.length > this._maxSize && (o = this._evictForCapacity(o)), this._items = Object.freeze(o), this.notify(e), this._scheduleEvictionTimer();
723
- }
724
- /**
725
- * Remove items by id(s).
726
- */
727
- remove(...t) {
728
- if (this._disposed)
729
- throw new Error("Cannot remove from disposed Collection");
730
- if (t.length === 0)
731
- return;
732
- const s = new Set(t), e = this._items.filter((n) => !s.has(n.id));
733
- if (e.length === this._items.length)
734
- return;
735
- const i = this._items;
736
- this._items = Object.freeze(e);
737
- for (const n of t)
738
- this._index.delete(n), this._timestamps?.delete(n);
739
- this.notify(i), this._scheduleEvictionTimer();
654
+ this._external ? this._external.upsert(...t) : super.upsert(...t);
740
655
  }
741
- /**
742
- * Update an item by id with partial changes.
743
- */
744
656
  update(t, s) {
745
- if (this._disposed)
746
- throw new Error("Cannot update disposed Collection");
747
- const e = this._items.findIndex((u) => u.id === t);
748
- if (e === -1)
749
- return;
750
- const i = this._items[e], n = { ...i, ...s, id: t };
751
- if (!Object.keys(s).some((u) => s[u] !== i[u]))
752
- return;
753
- const l = this._items, h = [...l];
754
- h[e] = n, this._items = Object.freeze(h), this._index.set(t, n), this.notify(l);
657
+ this._external ? this._external.update(t, s) : super.update(t, s);
658
+ }
659
+ remove(...t) {
660
+ this._external ? this._external.remove(...t) : super.remove(...t);
755
661
  }
756
- /**
757
- * Replace all items.
758
- */
759
662
  reset(t) {
760
- if (this._disposed)
761
- throw new Error("Cannot reset disposed Collection");
762
- const s = this._items;
763
- if (this._timestamps) {
764
- this._timestamps.clear();
765
- const i = Date.now();
766
- for (const n of t)
767
- this._timestamps.set(n.id, i);
768
- }
769
- let e = [...t];
770
- this._maxSize > 0 && e.length > this._maxSize && (e = this._evictForCapacity(e)), this._items = Object.freeze(e), this.rebuildIndex(), this.notify(s), this._scheduleEvictionTimer();
663
+ this._external ? this._external.reset(t) : super.reset(t);
771
664
  }
772
- /**
773
- * Remove all items.
774
- */
775
665
  clear() {
776
- if (this._disposed)
777
- throw new Error("Cannot clear disposed Collection");
778
- if (this._items.length === 0)
779
- return;
780
- const t = this._items;
781
- this._items = Object.freeze([]), this._index.clear(), this._timestamps?.clear(), this._clearEvictionTimer(), this.notify(t);
666
+ this._external ? this._external.clear() : super.clear();
782
667
  }
783
- /**
784
- * Snapshot current state, apply callback mutations, and return a rollback function.
785
- * Rollback restores items to pre-callback state regardless of later mutations.
786
- */
787
668
  optimistic(t) {
788
- if (this._disposed)
789
- throw new Error("Cannot perform optimistic update on disposed Collection");
790
- const s = this._items, e = this._timestamps ? new Map(this._timestamps) : null;
791
- t();
792
- let i = !1;
793
- return () => {
794
- if (i || this._disposed) return;
795
- i = !0;
796
- const n = this._items;
797
- this._items = s, e && (this._timestamps = e), this.rebuildIndex(), this.notify(n), this._scheduleEvictionTimer();
798
- };
669
+ return this._external ? this._external.optimistic(t) : super.optimistic(t);
799
670
  }
800
- // ── Query Methods (pure, no notification) ──
801
- /**
802
- * Get item by id.
803
- */
804
671
  get(t) {
805
- return this._index.get(t);
672
+ return this._external ? this._external.get(t) : super.get(t);
806
673
  }
807
- /**
808
- * Check if item exists by id.
809
- */
810
674
  has(t) {
811
- return this._index.has(t);
675
+ return this._external ? this._external.has(t) : super.has(t);
812
676
  }
813
- /**
814
- * Find first item matching predicate.
815
- */
816
677
  find(t) {
817
- return this._items.find(t);
678
+ return this._external ? this._external.find(t) : super.find(t);
818
679
  }
819
- /**
820
- * Filter items matching predicate.
821
- */
822
680
  filter(t) {
823
- return this._items.filter(t);
681
+ return this._external ? this._external.filter(t) : super.filter(t);
824
682
  }
825
- /**
826
- * Return sorted copy.
827
- */
828
683
  sorted(t) {
829
- return [...this._items].sort(t);
684
+ return this._external ? this._external.sorted(t) : super.sorted(t);
830
685
  }
831
- /**
832
- * Map items to new array.
833
- */
834
686
  map(t) {
835
- return this._items.map(t);
687
+ return this._external ? this._external.map(t) : super.map(t);
836
688
  }
837
- // ── Subscribable interface ──
838
- /** Subscribes to state changes. Returns an unsubscribe function. */
839
689
  subscribe(t) {
840
- return this._disposed ? () => {
841
- } : (this._listeners.add(t), () => {
842
- this._listeners.delete(t);
843
- });
690
+ return this.disposed ? () => {
691
+ } : this._external ? this._external.subscribe(t) : super.subscribe(t);
844
692
  }
845
- /** Tears down the instance, releasing all subscriptions and resources. */
846
- dispose() {
847
- if (!this._disposed) {
848
- if (this._disposed = !0, this._clearEvictionTimer(), this._abortController?.abort(), this._cleanups) {
849
- for (const t of this._cleanups) t();
850
- this._cleanups = null;
851
- }
852
- this.onDispose?.(), this._listeners.clear(), this._index.clear(), this._timestamps?.clear();
693
+ // ── Async tracking API ────────────────────────────────────────
694
+ /** Proxy providing `TaskState` (loading, error, errorCode) per async method. */
695
+ get async() {
696
+ if (!this._asyncProxy) {
697
+ const t = this;
698
+ this._asyncProxy = new Proxy({}, {
699
+ get(s, e) {
700
+ return t._asyncSnapshots.get(e) ?? D;
701
+ },
702
+ has(s, e) {
703
+ return t._asyncSnapshots.has(e);
704
+ },
705
+ ownKeys() {
706
+ return Array.from(t._asyncSnapshots.keys());
707
+ },
708
+ getOwnPropertyDescriptor(s, e) {
709
+ if (t._asyncSnapshots.has(e))
710
+ return { configurable: !0, enumerable: !0, value: t._asyncSnapshots.get(e) };
711
+ }
712
+ });
853
713
  }
714
+ return this._asyncProxy;
854
715
  }
855
- /** Registers a cleanup function to be called on dispose. @protected */
856
- addCleanup(t) {
857
- this._cleanups || (this._cleanups = []), this._cleanups.push(t);
716
+ /** Subscribes to async state changes. Used by `useAsync` and `useInstance` for React integration. */
717
+ subscribeAsync(t) {
718
+ return this.disposed ? () => {
719
+ } : (this._asyncListeners.add(t), () => {
720
+ this._asyncListeners.delete(t);
721
+ });
858
722
  }
859
- notify(t) {
860
- for (const s of this._listeners)
861
- s(this._items, t);
862
- }
863
- rebuildIndex() {
864
- this._index.clear();
865
- for (const t of this._items)
866
- this._index.set(t.id, t);
867
- }
868
- // ── Eviction Internals ──
869
- _evictForCapacity(t) {
870
- const s = t.length - this._maxSize;
871
- if (s <= 0) return t;
872
- const e = t.slice(0, s), i = this._applyOnEvict(e, "capacity");
873
- if (i === !1 || i.length === 0) return t;
874
- const n = new Set(i.map((o) => o.id)), a = t.filter((o) => !n.has(o.id));
875
- for (const o of i)
876
- this._index.delete(o.id), this._timestamps?.delete(o.id);
877
- return a;
878
- }
879
- _applyOnEvict(t, s) {
880
- if (!this.onEvict) return t;
881
- const e = this.onEvict(t, s);
882
- if (e === !1) {
883
- if (x && s === "capacity" && this._maxSize > 0) {
884
- const i = this._items.length + t.length;
885
- i > this._maxSize * 2 && console.warn(
886
- `[mvc-kit] Collection exceeded 2x MAX_SIZE (${i}/${this._maxSize}). onEvict is vetoing eviction — this may cause unbounded growth.`
723
+ // ── Private: async tracking internals ─────────────────────────
724
+ _notifyAsync() {
725
+ for (const t of this._asyncListeners)
726
+ t();
727
+ }
728
+ _guardReservedKeys() {
729
+ b(this, v.prototype, (t) => {
730
+ if (w.includes(t))
731
+ throw new Error(
732
+ `[mvc-kit] "${t}" is a reserved property on Resource and cannot be overridden.`
887
733
  );
888
- }
889
- return !1;
890
- }
891
- if (Array.isArray(e)) {
892
- const i = new Set(t.map((n) => n.id));
893
- return e.filter((n) => i.has(n.id));
894
- }
895
- return t;
896
- }
897
- _sweepExpired() {
898
- if (this._disposed || !this._timestamps || this._ttl <= 0) return;
899
- const t = Date.now(), s = this._ttl, e = [];
900
- for (const o of this._items) {
901
- const l = this._timestamps.get(o.id);
902
- l !== void 0 && t - l >= s && e.push(o);
903
- }
904
- if (e.length === 0) {
905
- this._scheduleEvictionTimer();
906
- return;
907
- }
908
- const i = this._applyOnEvict(e, "ttl");
909
- if (i === !1) {
910
- this._scheduleEvictionTimer();
911
- return;
912
- }
913
- if (i.length === 0) {
914
- this._scheduleEvictionTimer();
915
- return;
916
- }
917
- const n = new Set(i.map((o) => o.id)), a = this._items;
918
- this._items = Object.freeze(
919
- a.filter((o) => !n.has(o.id))
920
- );
921
- for (const o of i)
922
- this._index.delete(o.id), this._timestamps.delete(o.id);
923
- this.notify(a), this._scheduleEvictionTimer();
924
- }
925
- _scheduleEvictionTimer() {
926
- if (this._clearEvictionTimer(), this._disposed || !this._timestamps || this._ttl <= 0 || this._timestamps.size === 0) return;
927
- const t = Date.now(), s = this._ttl;
928
- let e = 1 / 0;
929
- for (const n of this._timestamps.values())
930
- n < e && (e = n);
931
- const i = Math.max(0, e + s - t);
932
- this._evictionTimer = setTimeout(() => this._sweepExpired(), i);
933
- }
934
- _clearEvictionTimer() {
935
- this._evictionTimer !== null && (clearTimeout(this._evictionTimer), this._evictionTimer = null);
734
+ });
735
+ }
736
+ _wrapMethods() {
737
+ for (const n of w)
738
+ if (Object.getOwnPropertyDescriptor(this, n)?.value !== void 0)
739
+ throw new Error(
740
+ `[mvc-kit] "${n}" is a reserved property on Resource and cannot be overridden.`
741
+ );
742
+ const t = this, s = /* @__PURE__ */ new Set(), e = [];
743
+ f && (this._activeOps = /* @__PURE__ */ new Map()), b(this, v.prototype, (n, o) => {
744
+ if (o.get || o.set || typeof o.value != "function" || n.startsWith("_") || k.has(n) || s.has(n)) return;
745
+ s.add(n);
746
+ const c = o.value;
747
+ let l = !1;
748
+ const p = function(...g) {
749
+ if (t.disposed) {
750
+ f && console.warn(`[mvc-kit] "${n}" called after dispose — ignored.`);
751
+ return;
752
+ }
753
+ f && !t._initialized && console.warn(
754
+ `[mvc-kit] "${n}" called before init(). Async tracking is active only after init().`
755
+ );
756
+ let u;
757
+ try {
758
+ u = c.apply(t, g);
759
+ } catch (a) {
760
+ throw a;
761
+ }
762
+ if (!u || typeof u.then != "function")
763
+ return l || (l = !0, t._asyncStates.delete(n), t._asyncSnapshots.delete(n), t[n] = c.bind(t)), u;
764
+ let i = t._asyncStates.get(n);
765
+ return i || (i = { loading: !1, error: null, errorCode: null, count: 0 }, t._asyncStates.set(n, i)), i.count++, i.loading = !0, i.error = null, i.errorCode = null, t._asyncSnapshots.set(n, Object.freeze({ loading: !0, error: null, errorCode: null })), t._notifyAsync(), f && t._activeOps && t._activeOps.set(n, (t._activeOps.get(n) ?? 0) + 1), u.then(
766
+ (a) => {
767
+ if (t.disposed) return a;
768
+ if (i.count--, i.loading = i.count > 0, t._asyncSnapshots.set(
769
+ n,
770
+ Object.freeze({ loading: i.loading, error: i.error, errorCode: i.errorCode })
771
+ ), t._notifyAsync(), f && t._activeOps) {
772
+ const _ = (t._activeOps.get(n) ?? 1) - 1;
773
+ _ <= 0 ? t._activeOps.delete(n) : t._activeOps.set(n, _);
774
+ }
775
+ return a;
776
+ },
777
+ (a) => {
778
+ if (O(a)) {
779
+ if (t.disposed || (i.count--, i.loading = i.count > 0, t._asyncSnapshots.set(
780
+ n,
781
+ Object.freeze({ loading: i.loading, error: i.error, errorCode: i.errorCode })
782
+ ), t._notifyAsync()), f && t._activeOps) {
783
+ const h = (t._activeOps.get(n) ?? 1) - 1;
784
+ h <= 0 ? t._activeOps.delete(n) : t._activeOps.set(n, h);
785
+ }
786
+ return;
787
+ }
788
+ if (t.disposed) return;
789
+ i.count--, i.loading = i.count > 0;
790
+ const _ = T(a);
791
+ if (i.error = _.message, i.errorCode = _.code, t._asyncSnapshots.set(
792
+ n,
793
+ Object.freeze({ loading: i.loading, error: _.message, errorCode: _.code })
794
+ ), t._notifyAsync(), f && t._activeOps) {
795
+ const h = (t._activeOps.get(n) ?? 1) - 1;
796
+ h <= 0 ? t._activeOps.delete(n) : t._activeOps.set(n, h);
797
+ }
798
+ throw a;
799
+ }
800
+ );
801
+ };
802
+ e.push(n), t[n] = p;
803
+ }), e.length > 0 && this.addCleanup(() => {
804
+ const n = f && t._activeOps ? new Map(t._activeOps) : null;
805
+ for (const o of e)
806
+ f ? t[o] = () => {
807
+ console.warn(`[mvc-kit] "${o}" called after dispose — ignored.`);
808
+ } : t[o] = () => {
809
+ };
810
+ t._asyncListeners.clear(), t._asyncStates.clear(), t._asyncSnapshots.clear(), f && n && n.size > 0 && t._scheduleGhostCheck(n);
811
+ });
812
+ }
813
+ _scheduleGhostCheck(t) {
814
+ f && setTimeout(() => {
815
+ for (const [s, e] of t)
816
+ console.warn(
817
+ `[mvc-kit] Ghost async operation detected: "${s}" had ${e} pending call(s) when the Resource was disposed. Consider using disposeSignal to cancel in-flight work.`
818
+ );
819
+ }, this.constructor.GHOST_TIMEOUT);
936
820
  }
937
821
  }
938
- class I {
822
+ class L {
939
823
  _disposed = !1;
940
824
  _initialized = !1;
941
825
  _abortController = null;
@@ -977,7 +861,7 @@ class I {
977
861
  return this.addCleanup(e), e;
978
862
  }
979
863
  }
980
- class P {
864
+ class V {
981
865
  _disposed = !1;
982
866
  _initialized = !1;
983
867
  _abortController = null;
@@ -1014,13 +898,13 @@ class P {
1014
898
  this._cleanups || (this._cleanups = []), this._cleanups.push(t);
1015
899
  }
1016
900
  }
1017
- const g = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__, k = Object.freeze({
901
+ const y = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__, R = Object.freeze({
1018
902
  connected: !1,
1019
903
  reconnecting: !1,
1020
904
  attempt: 0,
1021
905
  error: null
1022
906
  });
1023
- class R {
907
+ class N {
1024
908
  // Static config (subclass overrides)
1025
909
  /** Base delay (ms) for reconnection backoff. */
1026
910
  static RECONNECT_BASE = 1e3;
@@ -1031,7 +915,7 @@ class R {
1031
915
  /** Maximum number of reconnection attempts before giving up. */
1032
916
  static MAX_ATTEMPTS = 1 / 0;
1033
917
  // ── Internal state ──────────────────────────────────────────────
1034
- _status = k;
918
+ _status = R;
1035
919
  _connState = 0;
1036
920
  _disposed = !1;
1037
921
  _initialized = !1;
@@ -1090,10 +974,10 @@ class R {
1090
974
  /** Initiates a connection with automatic reconnection on failure. */
1091
975
  connect() {
1092
976
  if (this._disposed) {
1093
- g && console.warn("[mvc-kit] connect() called after dispose — ignored.");
977
+ y && console.warn("[mvc-kit] connect() called after dispose — ignored.");
1094
978
  return;
1095
979
  }
1096
- g && !this._initialized && console.warn("[mvc-kit] connect() called before init()."), !(this._connState === 1 || this._connState === 2) && (this._reconnectTimer !== null && (clearTimeout(this._reconnectTimer), this._reconnectTimer = null), this._attemptConnect(0));
980
+ y && !this._initialized && console.warn("[mvc-kit] connect() called before init()."), !(this._connState === 1 || this._connState === 2) && (this._reconnectTimer !== null && (clearTimeout(this._reconnectTimer), this._reconnectTimer = null), this._attemptConnect(0));
1097
981
  }
1098
982
  /** Closes the connection and cancels any pending reconnection. */
1099
983
  disconnect() {
@@ -1113,13 +997,13 @@ class R {
1113
997
  /** Call from subclass when a message arrives from the transport. @protected */
1114
998
  receive(t, s) {
1115
999
  if (this._disposed) {
1116
- g && console.warn(`[mvc-kit] receive("${String(t)}") called after dispose — ignored.`);
1000
+ y && console.warn(`[mvc-kit] receive("${String(t)}") called after dispose — ignored.`);
1117
1001
  return;
1118
1002
  }
1119
1003
  const e = this._handlers.get(t);
1120
1004
  if (e)
1121
- for (const i of e)
1122
- i(s);
1005
+ for (const n of e)
1006
+ n(s);
1123
1007
  }
1124
1008
  /** Call from subclass when the transport connection drops unexpectedly. Triggers reconnection. @protected */
1125
1009
  disconnected() {
@@ -1137,8 +1021,8 @@ class R {
1137
1021
  }
1138
1022
  /** Subscribes to a message type, auto-removing the handler after the first invocation. */
1139
1023
  once(t, s) {
1140
- const e = this.on(t, (i) => {
1141
- e(), s(i);
1024
+ const e = this.on(t, (n) => {
1025
+ e(), s(n);
1142
1026
  });
1143
1027
  return e;
1144
1028
  }
@@ -1183,13 +1067,13 @@ class R {
1183
1067
  let e;
1184
1068
  try {
1185
1069
  e = this.open(s);
1186
- } catch (i) {
1187
- this._onOpenFailed(t, i);
1070
+ } catch (n) {
1071
+ this._onOpenFailed(t, n);
1188
1072
  return;
1189
1073
  }
1190
1074
  e && typeof e.then == "function" ? e.then(
1191
1075
  () => this._onOpenSucceeded(),
1192
- (i) => this._onOpenFailed(t, i)
1076
+ (n) => this._onOpenFailed(t, n)
1193
1077
  ) : this._onOpenSucceeded();
1194
1078
  }
1195
1079
  _onOpenSucceeded() {
@@ -1214,33 +1098,35 @@ class R {
1214
1098
  });
1215
1099
  return;
1216
1100
  }
1217
- const i = s instanceof Error ? s.message : s ? String(s) : null;
1101
+ const n = s instanceof Error ? s.message : s ? String(s) : null;
1218
1102
  this._setStatus({
1219
1103
  connected: !1,
1220
1104
  reconnecting: !0,
1221
1105
  attempt: t,
1222
- error: i
1106
+ error: n
1223
1107
  });
1224
- const n = this._calculateDelay(t - 1);
1108
+ const o = this._calculateDelay(t - 1);
1225
1109
  this._reconnectTimer = setTimeout(() => {
1226
1110
  this._reconnectTimer = null, this._attemptConnect(t);
1227
- }, n);
1111
+ }, o);
1228
1112
  }
1229
1113
  }
1230
1114
  export {
1231
- R as Channel,
1232
- D as Collection,
1233
- I as Controller,
1234
- w as EventBus,
1235
- C as HttpError,
1236
- j as Model,
1237
- P as Service,
1238
- m as ViewModel,
1239
- E as classifyError,
1240
- N as hasSingleton,
1241
- y as isAbortError,
1242
- $ as singleton,
1243
- L as teardown,
1244
- B as teardownAll
1115
+ N as Channel,
1116
+ A as Collection,
1117
+ L as Controller,
1118
+ E as EventBus,
1119
+ x as HttpError,
1120
+ $ as Model,
1121
+ U as PersistentCollection,
1122
+ v as Resource,
1123
+ V as Service,
1124
+ S as ViewModel,
1125
+ T as classifyError,
1126
+ B as hasSingleton,
1127
+ O as isAbortError,
1128
+ F as singleton,
1129
+ X as teardown,
1130
+ Y as teardownAll
1245
1131
  };
1246
1132
  //# sourceMappingURL=mvc-kit.js.map