mvc-kit 2.4.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -1
- package/agent-config/bin/setup.mjs +1 -0
- package/agent-config/claude-code/agents/mvc-kit-architect.md +1 -1
- package/agent-config/claude-code/skills/guide/anti-patterns.md +75 -1
- package/agent-config/claude-code/skills/guide/api-reference.md +40 -1
- package/agent-config/claude-code/skills/guide/patterns.md +40 -1
- package/agent-config/copilot/copilot-instructions.md +6 -2
- package/agent-config/cursor/cursorrules +6 -2
- package/agent-config/lib/install-claude.mjs +9 -0
- package/dist/PersistentCollection-B8kNECDj.cjs +2 -0
- package/dist/PersistentCollection-B8kNECDj.cjs.map +1 -0
- package/dist/PersistentCollection-BFrgskju.js +542 -0
- package/dist/PersistentCollection-BFrgskju.js.map +1 -0
- package/dist/PersistentCollection.d.ts +69 -0
- package/dist/PersistentCollection.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/mvc-kit.cjs +1 -1
- package/dist/mvc-kit.cjs.map +1 -1
- package/dist/mvc-kit.js +229 -558
- package/dist/mvc-kit.js.map +1 -1
- package/dist/react-native/NativeCollection.d.ts +65 -0
- package/dist/react-native/NativeCollection.d.ts.map +1 -0
- package/dist/react-native/index.d.ts +2 -0
- package/dist/react-native/index.d.ts.map +1 -0
- package/dist/react-native.cjs +2 -0
- package/dist/react-native.cjs.map +1 -0
- package/dist/react-native.js +63 -0
- package/dist/react-native.js.map +1 -0
- package/dist/web/IndexedDBCollection.d.ts +37 -0
- package/dist/web/IndexedDBCollection.d.ts.map +1 -0
- package/dist/web/WebStorageCollection.d.ts +33 -0
- package/dist/web/WebStorageCollection.d.ts.map +1 -0
- package/dist/web/idb.d.ts +16 -0
- package/dist/web/idb.d.ts.map +1 -0
- package/dist/web/index.d.ts +3 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web.cjs +2 -0
- package/dist/web.cjs.map +1 -0
- package/dist/web.js +181 -0
- package/dist/web.js.map +1 -0
- package/package.json +22 -1
package/dist/mvc-kit.js
CHANGED
|
@@ -1,67 +1,69 @@
|
|
|
1
|
-
import { E
|
|
2
|
-
import { h as B, s as
|
|
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";
|
|
3
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
|
|
9
|
-
return
|
|
10
|
+
function O(r) {
|
|
11
|
+
return r instanceof Error && r.name === "AbortError";
|
|
10
12
|
}
|
|
11
|
-
function
|
|
12
|
-
return
|
|
13
|
+
function C(r) {
|
|
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 z(
|
|
15
|
-
return typeof
|
|
16
|
+
function z(r) {
|
|
17
|
+
return typeof r == "object" && r !== null && typeof r.status == "number" && typeof r.statusText == "string" && !(r instanceof Error);
|
|
16
18
|
}
|
|
17
|
-
function
|
|
18
|
-
return
|
|
19
|
+
function T(r) {
|
|
20
|
+
return r instanceof Error && r.name === "AbortError" ? {
|
|
19
21
|
code: "abort",
|
|
20
22
|
message: "Request was aborted",
|
|
21
|
-
original:
|
|
22
|
-
} :
|
|
23
|
-
code:
|
|
24
|
-
message:
|
|
25
|
-
status:
|
|
26
|
-
original:
|
|
27
|
-
} : z(
|
|
28
|
-
code:
|
|
29
|
-
message:
|
|
30
|
-
status:
|
|
31
|
-
original:
|
|
32
|
-
} :
|
|
23
|
+
original: r
|
|
24
|
+
} : r instanceof x ? {
|
|
25
|
+
code: C(r.status),
|
|
26
|
+
message: r.message,
|
|
27
|
+
status: r.status,
|
|
28
|
+
original: r
|
|
29
|
+
} : z(r) ? {
|
|
30
|
+
code: C(r.status),
|
|
31
|
+
message: r.statusText || `HTTP ${r.status}`,
|
|
32
|
+
status: r.status,
|
|
33
|
+
original: r
|
|
34
|
+
} : r instanceof TypeError && r.message.toLowerCase().includes("fetch") ? {
|
|
33
35
|
code: "network",
|
|
34
|
-
message:
|
|
35
|
-
original:
|
|
36
|
-
} :
|
|
36
|
+
message: r.message,
|
|
37
|
+
original: r
|
|
38
|
+
} : r instanceof Error && r.name === "TimeoutError" ? {
|
|
37
39
|
code: "timeout",
|
|
38
|
-
message:
|
|
39
|
-
original:
|
|
40
|
-
} :
|
|
40
|
+
message: r.message,
|
|
41
|
+
original: r
|
|
42
|
+
} : r instanceof Error ? {
|
|
41
43
|
code: "unknown",
|
|
42
|
-
message:
|
|
43
|
-
original:
|
|
44
|
+
message: r.message,
|
|
45
|
+
original: r
|
|
44
46
|
} : {
|
|
45
47
|
code: "unknown",
|
|
46
|
-
message: String(
|
|
47
|
-
original:
|
|
48
|
+
message: String(r),
|
|
49
|
+
original: r
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
|
-
const
|
|
51
|
-
function
|
|
52
|
-
return
|
|
52
|
+
const d = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__;
|
|
53
|
+
function M(r) {
|
|
54
|
+
return r !== null && typeof r == "object" && typeof r.subscribe == "function";
|
|
53
55
|
}
|
|
54
|
-
function
|
|
55
|
-
let e = Object.getPrototypeOf(
|
|
56
|
+
function b(r, t, s) {
|
|
57
|
+
let e = Object.getPrototypeOf(r);
|
|
56
58
|
for (; e && e !== t; ) {
|
|
57
|
-
const
|
|
58
|
-
for (const [
|
|
59
|
-
|
|
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
|
|
64
|
-
class
|
|
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 b {
|
|
|
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
|
|
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() {
|
|
@@ -124,7 +126,7 @@ class b {
|
|
|
124
126
|
*/
|
|
125
127
|
set(t) {
|
|
126
128
|
if (this._disposed) return;
|
|
127
|
-
if (
|
|
129
|
+
if (d && this._stateTracking) {
|
|
128
130
|
console.error(
|
|
129
131
|
"[mvc-kit] set() called inside a getter. Getters must be pure — they read state and return a value. They must never call set(), which would cause an infinite render loop. Move this logic to an action method."
|
|
130
132
|
);
|
|
@@ -132,13 +134,13 @@ class b {
|
|
|
132
134
|
}
|
|
133
135
|
const s = typeof t == "function" ? t(this._state) : t;
|
|
134
136
|
if (!Object.keys(s).some(
|
|
135
|
-
(
|
|
137
|
+
(l) => s[l] !== this._state[l]
|
|
136
138
|
))
|
|
137
139
|
return;
|
|
138
|
-
const
|
|
139
|
-
this._state = c, this._revision++, this.onSet?.(
|
|
140
|
-
for (const
|
|
141
|
-
|
|
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 b {
|
|
|
198
200
|
const t = this;
|
|
199
201
|
this._asyncProxy = new Proxy({}, {
|
|
200
202
|
get(s, e) {
|
|
201
|
-
return t._asyncSnapshots.get(e) ??
|
|
203
|
+
return t._asyncSnapshots.get(e) ?? j;
|
|
202
204
|
},
|
|
203
205
|
has(s, e) {
|
|
204
206
|
return t._asyncSnapshots.has(e);
|
|
@@ -234,92 +236,92 @@ class b {
|
|
|
234
236
|
}
|
|
235
237
|
}
|
|
236
238
|
_guardReservedKeys() {
|
|
237
|
-
|
|
238
|
-
if (
|
|
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
|
|
246
|
-
if (Object.getOwnPropertyDescriptor(this,
|
|
247
|
+
for (const n of m)
|
|
248
|
+
if (Object.getOwnPropertyDescriptor(this, n)?.value !== void 0)
|
|
247
249
|
throw new Error(
|
|
248
|
-
`[mvc-kit] "${
|
|
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
|
-
|
|
252
|
-
if (
|
|
253
|
-
s.add(
|
|
254
|
-
const c =
|
|
255
|
-
let
|
|
256
|
-
const
|
|
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
|
-
|
|
260
|
+
d && console.warn(`[mvc-kit] "${n}" called after dispose — ignored.`);
|
|
259
261
|
return;
|
|
260
262
|
}
|
|
261
|
-
|
|
262
|
-
`[mvc-kit] "${
|
|
263
|
+
d && !t._initialized && console.warn(
|
|
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 = c.apply(t,
|
|
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
|
|
272
|
-
let
|
|
273
|
-
return
|
|
274
|
-
(
|
|
275
|
-
if (t._disposed) return
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
Object.freeze({ loading:
|
|
279
|
-
), t._notifyAsync(),
|
|
280
|
-
const
|
|
281
|
-
|
|
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 })
|
|
281
|
+
), t._notifyAsync(), d && t._activeOps) {
|
|
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 (
|
|
287
|
-
if (t._disposed || (
|
|
288
|
-
|
|
289
|
-
Object.freeze({ loading:
|
|
290
|
-
), t._notifyAsync()),
|
|
291
|
-
const
|
|
292
|
-
|
|
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 })
|
|
292
|
+
), t._notifyAsync()), d && t._activeOps) {
|
|
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
|
-
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
Object.freeze({ loading:
|
|
302
|
-
), t._notifyAsync(),
|
|
303
|
-
const
|
|
304
|
-
|
|
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 })
|
|
304
|
+
), t._notifyAsync(), d && t._activeOps) {
|
|
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(
|
|
312
|
+
e.push(n), t[n] = p;
|
|
311
313
|
}), e.length > 0 && this.addCleanup(() => {
|
|
312
|
-
const
|
|
313
|
-
for (const
|
|
314
|
-
|
|
315
|
-
console.warn(`[mvc-kit] "${
|
|
316
|
-
} : t[
|
|
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(),
|
|
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) {
|
|
322
|
-
|
|
324
|
+
d && setTimeout(() => {
|
|
323
325
|
for (const [s, e] of t)
|
|
324
326
|
console.warn(
|
|
325
327
|
`[mvc-kit] Ghost async operation detected: "${s}" had ${e} pending call(s) when the ViewModel was disposed. Consider using disposeSignal to cancel in-flight work.`
|
|
@@ -371,15 +373,15 @@ class b {
|
|
|
371
373
|
_trackSubscribables() {
|
|
372
374
|
for (const t of Object.getOwnPropertyNames(this)) {
|
|
373
375
|
const s = this[t];
|
|
374
|
-
if (!
|
|
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
|
|
382
|
-
|
|
383
|
+
for (const n of this._listeners)
|
|
384
|
+
n(this._state, this._state);
|
|
383
385
|
}
|
|
384
386
|
})
|
|
385
387
|
};
|
|
@@ -400,7 +402,7 @@ class b {
|
|
|
400
402
|
*/
|
|
401
403
|
_memoizeGetters() {
|
|
402
404
|
const t = /* @__PURE__ */ new Set();
|
|
403
|
-
|
|
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,50 +417,50 @@ class b {
|
|
|
415
417
|
* Tier 3 (slow): at least one dep changed → full recompute with tracking
|
|
416
418
|
*/
|
|
417
419
|
_wrapGetter(t, s) {
|
|
418
|
-
let e,
|
|
420
|
+
let e, n = -1, o, c, l;
|
|
419
421
|
Object.defineProperty(this, t, {
|
|
420
422
|
get: () => {
|
|
421
|
-
if (this._disposed ||
|
|
423
|
+
if (this._disposed || n === this._revision)
|
|
422
424
|
return e;
|
|
423
|
-
if (
|
|
424
|
-
let
|
|
425
|
-
for (const [
|
|
426
|
-
if (this._state[
|
|
427
|
-
|
|
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 (
|
|
431
|
-
for (const [
|
|
432
|
-
const
|
|
433
|
-
if (
|
|
434
|
-
|
|
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 (
|
|
439
|
-
return
|
|
440
|
+
if (i)
|
|
441
|
+
return n = this._revision, e;
|
|
440
442
|
}
|
|
441
|
-
const
|
|
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 (
|
|
446
|
-
throw this._stateTracking =
|
|
447
|
+
} catch (i) {
|
|
448
|
+
throw this._stateTracking = p, this._sourceTracking = g, i;
|
|
447
449
|
}
|
|
448
|
-
|
|
450
|
+
o = this._stateTracking;
|
|
449
451
|
const u = this._sourceTracking;
|
|
450
|
-
if (this._stateTracking =
|
|
451
|
-
for (const
|
|
452
|
-
if (
|
|
453
|
-
for (const [
|
|
454
|
-
|
|
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);
|
|
455
457
|
c = /* @__PURE__ */ new Map();
|
|
456
|
-
for (const
|
|
457
|
-
c.set(
|
|
458
|
-
|
|
459
|
-
for (const [
|
|
460
|
-
|
|
461
|
-
return
|
|
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
|
|
@@ -531,13 +533,13 @@ class $ {
|
|
|
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
|
-
(
|
|
536
|
+
(l) => s[l] !== this._state[l]
|
|
535
537
|
))
|
|
536
538
|
return;
|
|
537
|
-
const
|
|
538
|
-
this._state = c, this.onSet?.(
|
|
539
|
-
for (const
|
|
540
|
-
|
|
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,349 +596,17 @@ class $ {
|
|
|
594
596
|
return this.addCleanup(e), e;
|
|
595
597
|
}
|
|
596
598
|
shallowEqual(t, s) {
|
|
597
|
-
const e = Object.keys(t),
|
|
598
|
-
if (e.length !==
|
|
599
|
+
const e = Object.keys(t), n = Object.keys(s);
|
|
600
|
+
if (e.length !== n.length)
|
|
599
601
|
return !1;
|
|
600
|
-
for (const
|
|
601
|
-
if (t[
|
|
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
|
|
607
|
-
class
|
|
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);
|
|
633
|
-
}
|
|
634
|
-
this._items = Object.freeze(s), this.rebuildIndex(), this._scheduleEvictionTimer();
|
|
635
|
-
}
|
|
636
|
-
/**
|
|
637
|
-
* Alias for Subscribable compatibility.
|
|
638
|
-
*/
|
|
639
|
-
get state() {
|
|
640
|
-
return this._items;
|
|
641
|
-
}
|
|
642
|
-
/** The raw readonly array of items. */
|
|
643
|
-
get items() {
|
|
644
|
-
return this._items;
|
|
645
|
-
}
|
|
646
|
-
/** Number of items in the collection. */
|
|
647
|
-
get length() {
|
|
648
|
-
return this._items.length;
|
|
649
|
-
}
|
|
650
|
-
/** Whether this instance has been disposed. */
|
|
651
|
-
get disposed() {
|
|
652
|
-
return this._disposed;
|
|
653
|
-
}
|
|
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
|
-
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 c of t)
|
|
676
|
-
!this._index.has(c.id) && !s.has(c.id) && (e.push(c), s.add(c.id));
|
|
677
|
-
if (e.length === 0) return;
|
|
678
|
-
const i = this._items;
|
|
679
|
-
let n = [...i, ...e];
|
|
680
|
-
for (const c of e)
|
|
681
|
-
this._index.set(c.id, c);
|
|
682
|
-
if (this._timestamps) {
|
|
683
|
-
const c = Date.now();
|
|
684
|
-
for (const a of e)
|
|
685
|
-
this._timestamps.set(a.id, c);
|
|
686
|
-
}
|
|
687
|
-
this._maxSize > 0 && n.length > this._maxSize && (n = this._evictForCapacity(n)), this._items = Object.freeze(n), this.notify(i), this._scheduleEvictionTimer();
|
|
688
|
-
}
|
|
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
|
-
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(), c = [];
|
|
705
|
-
for (const l of e)
|
|
706
|
-
if (s.has(l.id)) {
|
|
707
|
-
const _ = s.get(l.id);
|
|
708
|
-
_ !== l && (i = !0), c.push(_), n.add(l.id);
|
|
709
|
-
} else
|
|
710
|
-
c.push(l);
|
|
711
|
-
for (const [l, _] of s)
|
|
712
|
-
n.has(l) || (c.push(_), i = !0);
|
|
713
|
-
if (!i) return;
|
|
714
|
-
if (this._timestamps) {
|
|
715
|
-
const l = Date.now();
|
|
716
|
-
for (const [_] of s)
|
|
717
|
-
this._timestamps.set(_, l);
|
|
718
|
-
}
|
|
719
|
-
for (const [l, _] of s)
|
|
720
|
-
this._index.set(l, _);
|
|
721
|
-
let a = c;
|
|
722
|
-
this._maxSize > 0 && a.length > this._maxSize && (a = this._evictForCapacity(a)), this._items = Object.freeze(a), 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();
|
|
740
|
-
}
|
|
741
|
-
/**
|
|
742
|
-
* Update an item by id with partial changes.
|
|
743
|
-
*/
|
|
744
|
-
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, _ = [...l];
|
|
754
|
-
_[e] = n, this._items = Object.freeze(_), this._index.set(t, n), this.notify(l);
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* Replace all items.
|
|
758
|
-
*/
|
|
759
|
-
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();
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* Remove all items.
|
|
774
|
-
*/
|
|
775
|
-
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);
|
|
782
|
-
}
|
|
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
|
-
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
|
-
};
|
|
799
|
-
}
|
|
800
|
-
// ── Query Methods (pure, no notification) ──
|
|
801
|
-
/**
|
|
802
|
-
* Get item by id.
|
|
803
|
-
*/
|
|
804
|
-
get(t) {
|
|
805
|
-
return this._index.get(t);
|
|
806
|
-
}
|
|
807
|
-
/**
|
|
808
|
-
* Check if item exists by id.
|
|
809
|
-
*/
|
|
810
|
-
has(t) {
|
|
811
|
-
return this._index.has(t);
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* Find first item matching predicate.
|
|
815
|
-
*/
|
|
816
|
-
find(t) {
|
|
817
|
-
return this._items.find(t);
|
|
818
|
-
}
|
|
819
|
-
/**
|
|
820
|
-
* Filter items matching predicate.
|
|
821
|
-
*/
|
|
822
|
-
filter(t) {
|
|
823
|
-
return this._items.filter(t);
|
|
824
|
-
}
|
|
825
|
-
/**
|
|
826
|
-
* Return sorted copy.
|
|
827
|
-
*/
|
|
828
|
-
sorted(t) {
|
|
829
|
-
return [...this._items].sort(t);
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Map items to new array.
|
|
833
|
-
*/
|
|
834
|
-
map(t) {
|
|
835
|
-
return this._items.map(t);
|
|
836
|
-
}
|
|
837
|
-
// ── Subscribable interface ──
|
|
838
|
-
/** Subscribes to state changes. Returns an unsubscribe function. */
|
|
839
|
-
subscribe(t) {
|
|
840
|
-
return this._disposed ? () => {
|
|
841
|
-
} : (this._listeners.add(t), () => {
|
|
842
|
-
this._listeners.delete(t);
|
|
843
|
-
});
|
|
844
|
-
}
|
|
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();
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
/** Registers a cleanup function to be called on dispose. @protected */
|
|
856
|
-
addCleanup(t) {
|
|
857
|
-
this._cleanups || (this._cleanups = []), this._cleanups.push(t);
|
|
858
|
-
}
|
|
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((a) => a.id)), c = t.filter((a) => !n.has(a.id));
|
|
875
|
-
for (const a of i)
|
|
876
|
-
this._index.delete(a.id), this._timestamps?.delete(a.id);
|
|
877
|
-
return c;
|
|
878
|
-
}
|
|
879
|
-
_applyOnEvict(t, s) {
|
|
880
|
-
if (!this.onEvict) return t;
|
|
881
|
-
const e = this.onEvict(t, s);
|
|
882
|
-
if (e === !1) {
|
|
883
|
-
if (D && 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.`
|
|
887
|
-
);
|
|
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 a of this._items) {
|
|
901
|
-
const l = this._timestamps.get(a.id);
|
|
902
|
-
l !== void 0 && t - l >= s && e.push(a);
|
|
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((a) => a.id)), c = this._items;
|
|
918
|
-
this._items = Object.freeze(
|
|
919
|
-
c.filter((a) => !n.has(a.id))
|
|
920
|
-
);
|
|
921
|
-
for (const a of i)
|
|
922
|
-
this._index.delete(a.id), this._timestamps.delete(a.id);
|
|
923
|
-
this.notify(c), 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);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
const m = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__, k = Object.freeze({ loading: !1, error: null, errorCode: null }), C = ["async", "subscribeAsync"], P = /* @__PURE__ */ new Set(["onInit", "onDispose"]);
|
|
939
|
-
class S extends I {
|
|
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 {
|
|
940
610
|
_external = null;
|
|
941
611
|
_initialized = !1;
|
|
942
612
|
// ── Async tracking fields ──
|
|
@@ -949,7 +619,7 @@ class S extends I {
|
|
|
949
619
|
static GHOST_TIMEOUT = 3e3;
|
|
950
620
|
constructor(t) {
|
|
951
621
|
const s = t != null && !Array.isArray(t);
|
|
952
|
-
if (super(s ? [] : t ?? []), s && (this._external = t,
|
|
622
|
+
if (super(s ? [] : t ?? []), s && (this._external = t, f)) {
|
|
953
623
|
const e = this.constructor;
|
|
954
624
|
(e.MAX_SIZE > 0 || e.TTL > 0) && console.warn(
|
|
955
625
|
`[mvc-kit] Resource "${e.name}" has MAX_SIZE or TTL set but uses an injected Collection. Configure these on the Collection instead.`
|
|
@@ -1027,7 +697,7 @@ class S extends I {
|
|
|
1027
697
|
const t = this;
|
|
1028
698
|
this._asyncProxy = new Proxy({}, {
|
|
1029
699
|
get(s, e) {
|
|
1030
|
-
return t._asyncSnapshots.get(e) ??
|
|
700
|
+
return t._asyncSnapshots.get(e) ?? D;
|
|
1031
701
|
},
|
|
1032
702
|
has(s, e) {
|
|
1033
703
|
return t._asyncSnapshots.has(e);
|
|
@@ -1056,92 +726,92 @@ class S extends I {
|
|
|
1056
726
|
t();
|
|
1057
727
|
}
|
|
1058
728
|
_guardReservedKeys() {
|
|
1059
|
-
|
|
1060
|
-
if (
|
|
729
|
+
b(this, v.prototype, (t) => {
|
|
730
|
+
if (w.includes(t))
|
|
1061
731
|
throw new Error(
|
|
1062
732
|
`[mvc-kit] "${t}" is a reserved property on Resource and cannot be overridden.`
|
|
1063
733
|
);
|
|
1064
734
|
});
|
|
1065
735
|
}
|
|
1066
736
|
_wrapMethods() {
|
|
1067
|
-
for (const
|
|
1068
|
-
if (Object.getOwnPropertyDescriptor(this,
|
|
737
|
+
for (const n of w)
|
|
738
|
+
if (Object.getOwnPropertyDescriptor(this, n)?.value !== void 0)
|
|
1069
739
|
throw new Error(
|
|
1070
|
-
`[mvc-kit] "${
|
|
740
|
+
`[mvc-kit] "${n}" is a reserved property on Resource and cannot be overridden.`
|
|
1071
741
|
);
|
|
1072
742
|
const t = this, s = /* @__PURE__ */ new Set(), e = [];
|
|
1073
|
-
|
|
1074
|
-
if (
|
|
1075
|
-
s.add(
|
|
1076
|
-
const c =
|
|
1077
|
-
let
|
|
1078
|
-
const
|
|
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) {
|
|
1079
749
|
if (t.disposed) {
|
|
1080
|
-
|
|
750
|
+
f && console.warn(`[mvc-kit] "${n}" called after dispose — ignored.`);
|
|
1081
751
|
return;
|
|
1082
752
|
}
|
|
1083
|
-
|
|
1084
|
-
`[mvc-kit] "${
|
|
753
|
+
f && !t._initialized && console.warn(
|
|
754
|
+
`[mvc-kit] "${n}" called before init(). Async tracking is active only after init().`
|
|
1085
755
|
);
|
|
1086
756
|
let u;
|
|
1087
757
|
try {
|
|
1088
|
-
u = c.apply(t,
|
|
1089
|
-
} catch (
|
|
1090
|
-
throw
|
|
758
|
+
u = c.apply(t, g);
|
|
759
|
+
} catch (a) {
|
|
760
|
+
throw a;
|
|
1091
761
|
}
|
|
1092
762
|
if (!u || typeof u.then != "function")
|
|
1093
|
-
return
|
|
1094
|
-
let
|
|
1095
|
-
return
|
|
1096
|
-
(
|
|
1097
|
-
if (t.disposed) return
|
|
1098
|
-
if (
|
|
1099
|
-
|
|
1100
|
-
Object.freeze({ loading:
|
|
1101
|
-
), t._notifyAsync(),
|
|
1102
|
-
const
|
|
1103
|
-
|
|
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, _);
|
|
1104
774
|
}
|
|
1105
|
-
return
|
|
775
|
+
return a;
|
|
1106
776
|
},
|
|
1107
|
-
(
|
|
1108
|
-
if (
|
|
1109
|
-
if (t.disposed || (
|
|
1110
|
-
|
|
1111
|
-
Object.freeze({ loading:
|
|
1112
|
-
), t._notifyAsync()),
|
|
1113
|
-
const
|
|
1114
|
-
|
|
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);
|
|
1115
785
|
}
|
|
1116
786
|
return;
|
|
1117
787
|
}
|
|
1118
788
|
if (t.disposed) return;
|
|
1119
|
-
|
|
1120
|
-
const
|
|
1121
|
-
if (
|
|
1122
|
-
|
|
1123
|
-
Object.freeze({ loading:
|
|
1124
|
-
), t._notifyAsync(),
|
|
1125
|
-
const
|
|
1126
|
-
|
|
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);
|
|
1127
797
|
}
|
|
1128
|
-
throw
|
|
798
|
+
throw a;
|
|
1129
799
|
}
|
|
1130
800
|
);
|
|
1131
801
|
};
|
|
1132
|
-
e.push(
|
|
802
|
+
e.push(n), t[n] = p;
|
|
1133
803
|
}), e.length > 0 && this.addCleanup(() => {
|
|
1134
|
-
const
|
|
1135
|
-
for (const
|
|
1136
|
-
|
|
1137
|
-
console.warn(`[mvc-kit] "${
|
|
1138
|
-
} : t[
|
|
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] = () => {
|
|
1139
809
|
};
|
|
1140
|
-
t._asyncListeners.clear(), t._asyncStates.clear(), t._asyncSnapshots.clear(),
|
|
810
|
+
t._asyncListeners.clear(), t._asyncStates.clear(), t._asyncSnapshots.clear(), f && n && n.size > 0 && t._scheduleGhostCheck(n);
|
|
1141
811
|
});
|
|
1142
812
|
}
|
|
1143
813
|
_scheduleGhostCheck(t) {
|
|
1144
|
-
|
|
814
|
+
f && setTimeout(() => {
|
|
1145
815
|
for (const [s, e] of t)
|
|
1146
816
|
console.warn(
|
|
1147
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.`
|
|
@@ -1228,7 +898,7 @@ class V {
|
|
|
1228
898
|
this._cleanups || (this._cleanups = []), this._cleanups.push(t);
|
|
1229
899
|
}
|
|
1230
900
|
}
|
|
1231
|
-
const
|
|
901
|
+
const y = typeof __MVC_KIT_DEV__ < "u" && __MVC_KIT_DEV__, R = Object.freeze({
|
|
1232
902
|
connected: !1,
|
|
1233
903
|
reconnecting: !1,
|
|
1234
904
|
attempt: 0,
|
|
@@ -1304,10 +974,10 @@ class N {
|
|
|
1304
974
|
/** Initiates a connection with automatic reconnection on failure. */
|
|
1305
975
|
connect() {
|
|
1306
976
|
if (this._disposed) {
|
|
1307
|
-
|
|
977
|
+
y && console.warn("[mvc-kit] connect() called after dispose — ignored.");
|
|
1308
978
|
return;
|
|
1309
979
|
}
|
|
1310
|
-
|
|
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));
|
|
1311
981
|
}
|
|
1312
982
|
/** Closes the connection and cancels any pending reconnection. */
|
|
1313
983
|
disconnect() {
|
|
@@ -1327,13 +997,13 @@ class N {
|
|
|
1327
997
|
/** Call from subclass when a message arrives from the transport. @protected */
|
|
1328
998
|
receive(t, s) {
|
|
1329
999
|
if (this._disposed) {
|
|
1330
|
-
|
|
1000
|
+
y && console.warn(`[mvc-kit] receive("${String(t)}") called after dispose — ignored.`);
|
|
1331
1001
|
return;
|
|
1332
1002
|
}
|
|
1333
1003
|
const e = this._handlers.get(t);
|
|
1334
1004
|
if (e)
|
|
1335
|
-
for (const
|
|
1336
|
-
|
|
1005
|
+
for (const n of e)
|
|
1006
|
+
n(s);
|
|
1337
1007
|
}
|
|
1338
1008
|
/** Call from subclass when the transport connection drops unexpectedly. Triggers reconnection. @protected */
|
|
1339
1009
|
disconnected() {
|
|
@@ -1351,8 +1021,8 @@ class N {
|
|
|
1351
1021
|
}
|
|
1352
1022
|
/** Subscribes to a message type, auto-removing the handler after the first invocation. */
|
|
1353
1023
|
once(t, s) {
|
|
1354
|
-
const e = this.on(t, (
|
|
1355
|
-
e(), s(
|
|
1024
|
+
const e = this.on(t, (n) => {
|
|
1025
|
+
e(), s(n);
|
|
1356
1026
|
});
|
|
1357
1027
|
return e;
|
|
1358
1028
|
}
|
|
@@ -1397,13 +1067,13 @@ class N {
|
|
|
1397
1067
|
let e;
|
|
1398
1068
|
try {
|
|
1399
1069
|
e = this.open(s);
|
|
1400
|
-
} catch (
|
|
1401
|
-
this._onOpenFailed(t,
|
|
1070
|
+
} catch (n) {
|
|
1071
|
+
this._onOpenFailed(t, n);
|
|
1402
1072
|
return;
|
|
1403
1073
|
}
|
|
1404
1074
|
e && typeof e.then == "function" ? e.then(
|
|
1405
1075
|
() => this._onOpenSucceeded(),
|
|
1406
|
-
(
|
|
1076
|
+
(n) => this._onOpenFailed(t, n)
|
|
1407
1077
|
) : this._onOpenSucceeded();
|
|
1408
1078
|
}
|
|
1409
1079
|
_onOpenSucceeded() {
|
|
@@ -1428,33 +1098,34 @@ class N {
|
|
|
1428
1098
|
});
|
|
1429
1099
|
return;
|
|
1430
1100
|
}
|
|
1431
|
-
const
|
|
1101
|
+
const n = s instanceof Error ? s.message : s ? String(s) : null;
|
|
1432
1102
|
this._setStatus({
|
|
1433
1103
|
connected: !1,
|
|
1434
1104
|
reconnecting: !0,
|
|
1435
1105
|
attempt: t,
|
|
1436
|
-
error:
|
|
1106
|
+
error: n
|
|
1437
1107
|
});
|
|
1438
|
-
const
|
|
1108
|
+
const o = this._calculateDelay(t - 1);
|
|
1439
1109
|
this._reconnectTimer = setTimeout(() => {
|
|
1440
1110
|
this._reconnectTimer = null, this._attemptConnect(t);
|
|
1441
|
-
},
|
|
1111
|
+
}, o);
|
|
1442
1112
|
}
|
|
1443
1113
|
}
|
|
1444
1114
|
export {
|
|
1445
1115
|
N as Channel,
|
|
1446
|
-
|
|
1116
|
+
A as Collection,
|
|
1447
1117
|
L as Controller,
|
|
1448
|
-
|
|
1118
|
+
E as EventBus,
|
|
1449
1119
|
x as HttpError,
|
|
1450
1120
|
$ as Model,
|
|
1451
|
-
|
|
1121
|
+
U as PersistentCollection,
|
|
1122
|
+
v as Resource,
|
|
1452
1123
|
V as Service,
|
|
1453
|
-
|
|
1454
|
-
|
|
1124
|
+
S as ViewModel,
|
|
1125
|
+
T as classifyError,
|
|
1455
1126
|
B as hasSingleton,
|
|
1456
|
-
|
|
1457
|
-
|
|
1127
|
+
O as isAbortError,
|
|
1128
|
+
F as singleton,
|
|
1458
1129
|
X as teardown,
|
|
1459
1130
|
Y as teardownAll
|
|
1460
1131
|
};
|