@graphrefly/graphrefly 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -14
- package/dist/{chunk-HP7OKEOE.js → chunk-A2AJJOSJ.js} +3 -3
- package/dist/chunk-A2AJJOSJ.js.map +1 -0
- package/dist/{chunk-CP6MNKAA.js → chunk-E7OH6ZAZ.js} +10 -4
- package/dist/{chunk-CP6MNKAA.js.map → chunk-E7OH6ZAZ.js.map} +1 -1
- package/dist/chunk-LR2CLSEF.js +106 -0
- package/dist/chunk-LR2CLSEF.js.map +1 -0
- package/dist/{chunk-5X3LAO3B.js → chunk-QTZSBQGJ.js} +79 -20
- package/dist/chunk-QTZSBQGJ.js.map +1 -0
- package/dist/{chunk-V3UACY6A.js → chunk-TZLX4KIT.js} +790 -203
- package/dist/chunk-TZLX4KIT.js.map +1 -0
- package/dist/{chunk-QW7H3ICI.js → chunk-UCW3VWMN.js} +4 -4
- package/dist/{chunk-6W5SGIGB.js → chunk-WYI7YW54.js} +142 -30
- package/dist/chunk-WYI7YW54.js.map +1 -0
- package/dist/chunk-WZ2Z2CRV.js +32 -0
- package/dist/chunk-WZ2Z2CRV.js.map +1 -0
- package/dist/{chunk-Z4Y4FMQN.js → chunk-XCZPGOVP.js} +7 -7
- package/dist/{chunk-KWXPDASV.js → chunk-YWTP2XRJ.js} +2 -2
- package/dist/compat/nestjs/index.cjs +268 -61
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +4 -4
- package/dist/compat/nestjs/index.d.ts +4 -4
- package/dist/compat/nestjs/index.js +8 -7
- package/dist/core/index.cjs +163 -35
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +10 -4
- package/dist/extra/index.cjs +892 -221
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +4 -4
- package/dist/extra/index.d.ts +4 -4
- package/dist/extra/index.js +22 -3
- package/dist/graph/index.cjs +268 -61
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +3 -3
- package/dist/graph/index.d.ts +3 -3
- package/dist/graph/index.js +4 -4
- package/dist/{graph-CL_ZDAj9.d.cts → graph-DqTICAY2.d.cts} +69 -12
- package/dist/{graph-D18qmsNm.d.ts → graph-X9uwnD_z.d.ts} +69 -12
- package/dist/{index-C3BMRmmp.d.cts → index-3U0WxdD-.d.cts} +3 -3
- package/dist/{index-Bk_idZm1.d.cts → index-BP1t_38S.d.cts} +406 -61
- package/dist/{index-BtK55IE2.d.ts → index-BPCeYDS4.d.ts} +4 -2
- package/dist/{index-Bvy_6CaN.d.ts → index-BVG5pjin.d.ts} +50 -5
- package/dist/{index-C5mqLhMX.d.cts → index-BYEgosAX.d.cts} +50 -5
- package/dist/{index-D_geH2Bm.d.cts → index-BYa2YMat.d.cts} +3 -3
- package/dist/{index-CP_QvbWu.d.ts → index-DLO8wnYU.d.ts} +3 -3
- package/dist/{index-B7eOdgEx.d.ts → index-DMv1Etbi.d.ts} +3 -3
- package/dist/{index-BvhgZRHK.d.cts → index-DbwgQ4Cw.d.cts} +4 -2
- package/dist/{index-B2jmzVxL.d.ts → index-a5gHmH5b.d.ts} +406 -61
- package/dist/index.cjs +2966 -1790
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -14
- package/dist/index.d.ts +112 -14
- package/dist/index.js +385 -20
- package/dist/index.js.map +1 -1
- package/dist/{meta-BsF6Sag9.d.cts → meta-BJEU8fYz.d.cts} +31 -4
- package/dist/{meta-BsF6Sag9.d.ts → meta-BJEU8fYz.d.ts} +31 -4
- package/dist/patterns/reactive-layout/index.cjs +268 -61
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +3 -3
- package/dist/patterns/reactive-layout/index.d.ts +3 -3
- package/dist/patterns/reactive-layout/index.js +4 -4
- package/dist/{reactive-log-BfvfNWQh.d.cts → reactive-log-BfX6bOSZ.d.cts} +2 -2
- package/dist/{reactive-log-ohLmTXoZ.d.ts → reactive-log-RhgIog2Z.d.ts} +2 -2
- package/package.json +29 -18
- package/dist/chunk-5X3LAO3B.js.map +0 -1
- package/dist/chunk-6W5SGIGB.js.map +0 -1
- package/dist/chunk-HP7OKEOE.js.map +0 -1
- package/dist/chunk-O3PI7W45.js +0 -68
- package/dist/chunk-O3PI7W45.js.map +0 -1
- package/dist/chunk-V3UACY6A.js.map +0 -1
- /package/dist/{chunk-QW7H3ICI.js.map → chunk-UCW3VWMN.js.map} +0 -0
- /package/dist/{chunk-Z4Y4FMQN.js.map → chunk-XCZPGOVP.js.map} +0 -0
- /package/dist/{chunk-KWXPDASV.js.map → chunk-YWTP2XRJ.js.map} +0 -0
|
@@ -368,10 +368,14 @@ function partitionForBatch(messages) {
|
|
|
368
368
|
}
|
|
369
369
|
return { immediate, deferred, terminal };
|
|
370
370
|
}
|
|
371
|
-
function emitWithBatch(emit, messages, phase = 2) {
|
|
371
|
+
function emitWithBatch(emit, messages, phase = 2, options) {
|
|
372
372
|
if (messages.length === 0) {
|
|
373
373
|
return;
|
|
374
374
|
}
|
|
375
|
+
if (options?.strategy === "sequential") {
|
|
376
|
+
_emitSequential(emit, messages, phase);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
375
379
|
const queue = phase === 3 ? pendingPhase3 : pendingPhase2;
|
|
376
380
|
if (messages.length === 1) {
|
|
377
381
|
const t = messages[0][0];
|
|
@@ -412,6 +416,29 @@ function emitWithBatch(emit, messages, phase = 2) {
|
|
|
412
416
|
}
|
|
413
417
|
}
|
|
414
418
|
}
|
|
419
|
+
function _emitSequential(emit, messages, phase = 2) {
|
|
420
|
+
const dataQueue = phase === 3 ? pendingPhase3 : pendingPhase2;
|
|
421
|
+
for (const msg of messages) {
|
|
422
|
+
const tier = messageTier(msg[0]);
|
|
423
|
+
if (tier === 2) {
|
|
424
|
+
if (isBatching()) {
|
|
425
|
+
const m = msg;
|
|
426
|
+
dataQueue.push(() => emit([m]));
|
|
427
|
+
} else {
|
|
428
|
+
emit([msg]);
|
|
429
|
+
}
|
|
430
|
+
} else if (tier >= 3) {
|
|
431
|
+
if (isBatching()) {
|
|
432
|
+
const m = msg;
|
|
433
|
+
pendingPhase3.push(() => emit([m]));
|
|
434
|
+
} else {
|
|
435
|
+
emit([msg]);
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
emit([msg]);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
415
442
|
|
|
416
443
|
// src/core/clock.ts
|
|
417
444
|
function monotonicNs() {
|
|
@@ -520,6 +547,7 @@ function advanceVersion(info, newValue, hashFn) {
|
|
|
520
547
|
}
|
|
521
548
|
|
|
522
549
|
// src/core/node.ts
|
|
550
|
+
var NO_VALUE = /* @__PURE__ */ Symbol.for("graphrefly/NO_VALUE");
|
|
523
551
|
function createIntBitSet() {
|
|
524
552
|
let bits = 0;
|
|
525
553
|
return {
|
|
@@ -649,10 +677,10 @@ var NodeImpl = class {
|
|
|
649
677
|
this._hasDeps = deps.length > 0;
|
|
650
678
|
this._autoComplete = opts.completeWhenDepsComplete ?? true;
|
|
651
679
|
this._isSingleDep = deps.length === 1 && fn != null;
|
|
652
|
-
this._cached = opts.initial;
|
|
680
|
+
this._cached = "initial" in opts ? opts.initial : NO_VALUE;
|
|
653
681
|
this._status = this._hasDeps ? "disconnected" : "settled";
|
|
654
682
|
this._hashFn = opts.versioningHash ?? defaultHash;
|
|
655
|
-
this._versioning = opts.versioning != null ? createVersioning(opts.versioning, this._cached, {
|
|
683
|
+
this._versioning = opts.versioning != null ? createVersioning(opts.versioning, this._cached === NO_VALUE ? void 0 : this._cached, {
|
|
656
684
|
id: opts.versioningId,
|
|
657
685
|
hash: this._hashFn
|
|
658
686
|
}) : void 0;
|
|
@@ -736,10 +764,14 @@ var NodeImpl = class {
|
|
|
736
764
|
_applyVersioning(level, opts) {
|
|
737
765
|
if (this._versioning != null) return;
|
|
738
766
|
this._hashFn = opts?.hash ?? this._hashFn;
|
|
739
|
-
this._versioning = createVersioning(
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
767
|
+
this._versioning = createVersioning(
|
|
768
|
+
level,
|
|
769
|
+
this._cached === NO_VALUE ? void 0 : this._cached,
|
|
770
|
+
{
|
|
771
|
+
id: opts?.id,
|
|
772
|
+
hash: this._hashFn
|
|
773
|
+
}
|
|
774
|
+
);
|
|
743
775
|
}
|
|
744
776
|
hasGuard() {
|
|
745
777
|
return this._guard != null;
|
|
@@ -749,7 +781,7 @@ var NodeImpl = class {
|
|
|
749
781
|
return this._guard(normalizeActor(actor), "observe");
|
|
750
782
|
}
|
|
751
783
|
get() {
|
|
752
|
-
return this._cached;
|
|
784
|
+
return this._cached === NO_VALUE ? void 0 : this._cached;
|
|
753
785
|
}
|
|
754
786
|
down(messages, options) {
|
|
755
787
|
if (messages.length === 0) return;
|
|
@@ -806,6 +838,7 @@ var NodeImpl = class {
|
|
|
806
838
|
}
|
|
807
839
|
if (this._terminal && this._opts.resubscribable) {
|
|
808
840
|
this._terminal = false;
|
|
841
|
+
this._cached = NO_VALUE;
|
|
809
842
|
this._status = this._hasDeps ? "disconnected" : "settled";
|
|
810
843
|
this._opts.onResubscribe?.();
|
|
811
844
|
}
|
|
@@ -905,7 +938,7 @@ var NodeImpl = class {
|
|
|
905
938
|
const cleanupFn = this._cleanup;
|
|
906
939
|
this._cleanup = void 0;
|
|
907
940
|
cleanupFn?.();
|
|
908
|
-
this._cached =
|
|
941
|
+
this._cached = NO_VALUE;
|
|
909
942
|
this._lastDepValues = void 0;
|
|
910
943
|
}
|
|
911
944
|
this._status = statusAfterMessage(this._status, m);
|
|
@@ -914,7 +947,7 @@ var NodeImpl = class {
|
|
|
914
947
|
}
|
|
915
948
|
if (t === TEARDOWN) {
|
|
916
949
|
if (this._opts.resetOnTeardown) {
|
|
917
|
-
this._cached =
|
|
950
|
+
this._cached = NO_VALUE;
|
|
918
951
|
}
|
|
919
952
|
const teardownCleanup = this._cleanup;
|
|
920
953
|
this._cleanup = void 0;
|
|
@@ -945,7 +978,15 @@ var NodeImpl = class {
|
|
|
945
978
|
}
|
|
946
979
|
_emitAutoValue(value) {
|
|
947
980
|
const wasDirty = this._status === "dirty";
|
|
948
|
-
|
|
981
|
+
let unchanged;
|
|
982
|
+
try {
|
|
983
|
+
unchanged = this._cached !== NO_VALUE && this._equals(this._cached, value);
|
|
984
|
+
} catch (eqErr) {
|
|
985
|
+
const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
|
|
986
|
+
const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
|
|
987
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
949
990
|
if (unchanged) {
|
|
950
991
|
this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
|
|
951
992
|
return;
|
|
@@ -992,7 +1033,9 @@ var NodeImpl = class {
|
|
|
992
1033
|
if (out === void 0) return;
|
|
993
1034
|
this._emitAutoValue(out);
|
|
994
1035
|
} catch (err) {
|
|
995
|
-
|
|
1036
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1037
|
+
const wrapped = new Error(`Node "${this.name}": fn threw: ${errMsg}`, { cause: err });
|
|
1038
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
996
1039
|
}
|
|
997
1040
|
}
|
|
998
1041
|
_onDepDirty(index) {
|
|
@@ -1027,7 +1070,11 @@ var NodeImpl = class {
|
|
|
1027
1070
|
try {
|
|
1028
1071
|
if (this._onMessage(msg, index, this._actions)) continue;
|
|
1029
1072
|
} catch (err) {
|
|
1030
|
-
|
|
1073
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1074
|
+
const wrapped = new Error(`Node "${this.name}": onMessage threw: ${errMsg}`, {
|
|
1075
|
+
cause: err
|
|
1076
|
+
});
|
|
1077
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
1031
1078
|
return;
|
|
1032
1079
|
}
|
|
1033
1080
|
}
|
|
@@ -1168,7 +1215,7 @@ var DynamicNodeImpl = class {
|
|
|
1168
1215
|
_actions;
|
|
1169
1216
|
_boundEmitToSinks;
|
|
1170
1217
|
// Mutable state
|
|
1171
|
-
_cached;
|
|
1218
|
+
_cached = NO_VALUE;
|
|
1172
1219
|
_status = "disconnected";
|
|
1173
1220
|
_terminal = false;
|
|
1174
1221
|
_connected = false;
|
|
@@ -1262,7 +1309,7 @@ var DynamicNodeImpl = class {
|
|
|
1262
1309
|
return this._guard(normalizeActor(actor), "observe");
|
|
1263
1310
|
}
|
|
1264
1311
|
get() {
|
|
1265
|
-
return this._cached;
|
|
1312
|
+
return this._cached === NO_VALUE ? void 0 : this._cached;
|
|
1266
1313
|
}
|
|
1267
1314
|
down(messages, options) {
|
|
1268
1315
|
if (messages.length === 0) return;
|
|
@@ -1320,6 +1367,7 @@ var DynamicNodeImpl = class {
|
|
|
1320
1367
|
}
|
|
1321
1368
|
if (this._terminal && this._resubscribable) {
|
|
1322
1369
|
this._terminal = false;
|
|
1370
|
+
this._cached = NO_VALUE;
|
|
1323
1371
|
this._status = "disconnected";
|
|
1324
1372
|
this._onResubscribe?.();
|
|
1325
1373
|
}
|
|
@@ -1397,10 +1445,13 @@ var DynamicNodeImpl = class {
|
|
|
1397
1445
|
const t = m[0];
|
|
1398
1446
|
if (t === DATA) this._cached = m[1];
|
|
1399
1447
|
if (t === INVALIDATE) {
|
|
1400
|
-
this._cached =
|
|
1448
|
+
this._cached = NO_VALUE;
|
|
1449
|
+
this._status = "dirty";
|
|
1401
1450
|
}
|
|
1402
|
-
if (t === DATA
|
|
1451
|
+
if (t === DATA) {
|
|
1403
1452
|
this._status = "settled";
|
|
1453
|
+
} else if (t === RESOLVED) {
|
|
1454
|
+
this._status = "resolved";
|
|
1404
1455
|
} else if (t === DIRTY) {
|
|
1405
1456
|
this._status = "dirty";
|
|
1406
1457
|
} else if (t === COMPLETE) {
|
|
@@ -1411,7 +1462,7 @@ var DynamicNodeImpl = class {
|
|
|
1411
1462
|
this._terminal = true;
|
|
1412
1463
|
}
|
|
1413
1464
|
if (t === TEARDOWN) {
|
|
1414
|
-
if (this._resetOnTeardown) this._cached =
|
|
1465
|
+
if (this._resetOnTeardown) this._cached = NO_VALUE;
|
|
1415
1466
|
try {
|
|
1416
1467
|
this._propagateToMeta(t);
|
|
1417
1468
|
} finally {
|
|
@@ -1434,7 +1485,15 @@ var DynamicNodeImpl = class {
|
|
|
1434
1485
|
}
|
|
1435
1486
|
_emitAutoValue(value) {
|
|
1436
1487
|
const wasDirty = this._status === "dirty";
|
|
1437
|
-
|
|
1488
|
+
let unchanged;
|
|
1489
|
+
try {
|
|
1490
|
+
unchanged = this._cached !== NO_VALUE && this._equals(this._cached, value);
|
|
1491
|
+
} catch (eqErr) {
|
|
1492
|
+
const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
|
|
1493
|
+
const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
|
|
1494
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1438
1497
|
if (unchanged) {
|
|
1439
1498
|
this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
|
|
1440
1499
|
return;
|
|
@@ -1600,6 +1659,19 @@ var DynamicNodeImpl = class {
|
|
|
1600
1659
|
};
|
|
1601
1660
|
|
|
1602
1661
|
// src/core/meta.ts
|
|
1662
|
+
function resolveDescribeFields(detail, fields) {
|
|
1663
|
+
if (fields != null && fields.length > 0) return new Set(fields);
|
|
1664
|
+
switch (detail) {
|
|
1665
|
+
case "standard":
|
|
1666
|
+
return /* @__PURE__ */ new Set(["type", "status", "value", "deps", "meta", "v"]);
|
|
1667
|
+
case "full":
|
|
1668
|
+
return null;
|
|
1669
|
+
// null = include everything
|
|
1670
|
+
case "minimal":
|
|
1671
|
+
default:
|
|
1672
|
+
return /* @__PURE__ */ new Set(["type", "deps"]);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1603
1675
|
function inferDescribeType(n) {
|
|
1604
1676
|
if (n._describeKind != null) return n._describeKind;
|
|
1605
1677
|
if (!n._hasDeps) return n._fn != null ? "producer" : "state";
|
|
@@ -1617,12 +1689,10 @@ function metaSnapshot(node2) {
|
|
|
1617
1689
|
}
|
|
1618
1690
|
return out;
|
|
1619
1691
|
}
|
|
1620
|
-
function describeNode(node2) {
|
|
1621
|
-
const
|
|
1622
|
-
const
|
|
1623
|
-
|
|
1624
|
-
meta.access = accessHintForGuard(guard);
|
|
1625
|
-
}
|
|
1692
|
+
function describeNode(node2, includeFields) {
|
|
1693
|
+
const all = includeFields == null;
|
|
1694
|
+
const metaKeys = !all && includeFields != null ? [...includeFields].filter((f) => f.startsWith("meta.")).map((f) => f.slice(5)) : null;
|
|
1695
|
+
const wantsMeta = all || includeFields.has("meta") || metaKeys != null && metaKeys.length > 0;
|
|
1626
1696
|
let type = "state";
|
|
1627
1697
|
let deps = [];
|
|
1628
1698
|
if (node2 instanceof NodeImpl) {
|
|
@@ -1632,20 +1702,36 @@ function describeNode(node2) {
|
|
|
1632
1702
|
type = node2._describeKind ?? "derived";
|
|
1633
1703
|
deps = [];
|
|
1634
1704
|
}
|
|
1635
|
-
const out = {
|
|
1636
|
-
|
|
1637
|
-
status
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1705
|
+
const out = { type, deps };
|
|
1706
|
+
if (all || includeFields.has("status")) {
|
|
1707
|
+
out.status = node2.status;
|
|
1708
|
+
}
|
|
1709
|
+
const guard = node2 instanceof NodeImpl && node2._guard || node2 instanceof DynamicNodeImpl && node2._guard || void 0;
|
|
1710
|
+
if (wantsMeta) {
|
|
1711
|
+
const rawMeta = { ...metaSnapshot(node2) };
|
|
1712
|
+
if (guard != null && rawMeta.access === void 0) {
|
|
1713
|
+
rawMeta.access = accessHintForGuard(guard);
|
|
1714
|
+
}
|
|
1715
|
+
if (metaKeys != null && metaKeys.length > 0 && !includeFields.has("meta")) {
|
|
1716
|
+
const filtered = {};
|
|
1717
|
+
for (const k of metaKeys) {
|
|
1718
|
+
if (k in rawMeta) filtered[k] = rawMeta[k];
|
|
1719
|
+
}
|
|
1720
|
+
out.meta = filtered;
|
|
1721
|
+
} else {
|
|
1722
|
+
out.meta = rawMeta;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1641
1725
|
if (node2.name != null) {
|
|
1642
1726
|
out.name = node2.name;
|
|
1643
1727
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1728
|
+
if (all || includeFields.has("value")) {
|
|
1729
|
+
try {
|
|
1730
|
+
out.value = node2.get();
|
|
1731
|
+
} catch {
|
|
1732
|
+
}
|
|
1647
1733
|
}
|
|
1648
|
-
if (node2.v != null) {
|
|
1734
|
+
if ((all || includeFields.has("v")) && node2.v != null) {
|
|
1649
1735
|
const vInfo = { id: node2.v.id, version: node2.v.version };
|
|
1650
1736
|
if ("cid" in node2.v) {
|
|
1651
1737
|
vInfo.cid = node2.v.cid;
|
|
@@ -1653,6 +1739,16 @@ function describeNode(node2) {
|
|
|
1653
1739
|
}
|
|
1654
1740
|
out.v = vInfo;
|
|
1655
1741
|
}
|
|
1742
|
+
if (all || includeFields.has("guard")) {
|
|
1743
|
+
if (guard != null) {
|
|
1744
|
+
out.guard = accessHintForGuard(guard);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
if (all || includeFields.has("lastMutation")) {
|
|
1748
|
+
if (node2.lastMutation != null) {
|
|
1749
|
+
out.lastMutation = node2.lastMutation;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1656
1752
|
return out;
|
|
1657
1753
|
}
|
|
1658
1754
|
|
|
@@ -1842,6 +1938,23 @@ function resolveSpyTheme(theme) {
|
|
|
1842
1938
|
reset: theme.reset ?? ""
|
|
1843
1939
|
};
|
|
1844
1940
|
}
|
|
1941
|
+
function resolveObserveDetail(opts) {
|
|
1942
|
+
if (opts == null) return {};
|
|
1943
|
+
const detail = opts.detail;
|
|
1944
|
+
if (detail === "full") {
|
|
1945
|
+
return {
|
|
1946
|
+
...opts,
|
|
1947
|
+
structured: opts.structured ?? true,
|
|
1948
|
+
timeline: opts.timeline ?? true,
|
|
1949
|
+
causal: opts.causal ?? true,
|
|
1950
|
+
derived: opts.derived ?? true
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
if (detail === "minimal") {
|
|
1954
|
+
return { ...opts, structured: opts.structured ?? true };
|
|
1955
|
+
}
|
|
1956
|
+
return opts;
|
|
1957
|
+
}
|
|
1845
1958
|
function assertLocalName(name, graphName, label) {
|
|
1846
1959
|
if (name === "") {
|
|
1847
1960
|
throw new Error(`Graph "${graphName}": ${label} name must be non-empty`);
|
|
@@ -2039,6 +2152,22 @@ var Graph = class _Graph {
|
|
|
2039
2152
|
if (this._defaultVersioningLevel != null) {
|
|
2040
2153
|
node2._applyVersioning(this._defaultVersioningLevel);
|
|
2041
2154
|
}
|
|
2155
|
+
if (node2._deps.length > 0) {
|
|
2156
|
+
for (const dep of node2._deps) {
|
|
2157
|
+
for (const [depName, depNode] of this._nodes) {
|
|
2158
|
+
if (depNode === dep) {
|
|
2159
|
+
this._edges.add(edgeKey(depName, name));
|
|
2160
|
+
break;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
for (const [otherName, otherNode] of this._nodes) {
|
|
2166
|
+
if (otherName === name) continue;
|
|
2167
|
+
if (otherNode instanceof NodeImpl && otherNode._deps.includes(node2)) {
|
|
2168
|
+
this._edges.add(edgeKey(name, otherName));
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2042
2171
|
}
|
|
2043
2172
|
}
|
|
2044
2173
|
/**
|
|
@@ -2425,6 +2554,9 @@ var Graph = class _Graph {
|
|
|
2425
2554
|
describe(options) {
|
|
2426
2555
|
const actor = options?.actor;
|
|
2427
2556
|
const filter = options?.filter;
|
|
2557
|
+
const includeFields = resolveDescribeFields(options?.detail, options?.fields);
|
|
2558
|
+
const isSpec = options?.format === "spec";
|
|
2559
|
+
const effectiveFields = isSpec ? resolveDescribeFields("minimal") : includeFields;
|
|
2428
2560
|
const targets = [];
|
|
2429
2561
|
this._collectObserveTargets("", targets);
|
|
2430
2562
|
const nodeToPath = /* @__PURE__ */ new Map();
|
|
@@ -2434,7 +2566,7 @@ var Graph = class _Graph {
|
|
|
2434
2566
|
const nodes = {};
|
|
2435
2567
|
for (const [p, n] of targets) {
|
|
2436
2568
|
if (actor != null && !n.allowsObserve(actor)) continue;
|
|
2437
|
-
const raw = describeNode(n);
|
|
2569
|
+
const raw = describeNode(n, effectiveFields);
|
|
2438
2570
|
const deps = n instanceof NodeImpl ? n._deps.map((d) => nodeToPath.get(d) ?? d.name ?? "") : [];
|
|
2439
2571
|
const { name: _name, ...rest } = raw;
|
|
2440
2572
|
const entry = { ...rest, deps };
|
|
@@ -2455,7 +2587,7 @@ var Graph = class _Graph {
|
|
|
2455
2587
|
continue;
|
|
2456
2588
|
}
|
|
2457
2589
|
if (normalizedKey === "metaHas") {
|
|
2458
|
-
if (!Object.hasOwn(entry.meta, String(fv))) {
|
|
2590
|
+
if (!Object.hasOwn(entry.meta ?? {}, String(fv))) {
|
|
2459
2591
|
match = false;
|
|
2460
2592
|
break;
|
|
2461
2593
|
}
|
|
@@ -2488,11 +2620,24 @@ var Graph = class _Graph {
|
|
|
2488
2620
|
const prefix = `${sg}${PATH_SEP}`;
|
|
2489
2621
|
return [...nodeKeys].some((k) => k === sg || k.startsWith(prefix));
|
|
2490
2622
|
}) : allSubgraphs;
|
|
2623
|
+
const graph = this;
|
|
2624
|
+
const baseOpts = options;
|
|
2491
2625
|
return {
|
|
2492
2626
|
name: this.name,
|
|
2493
2627
|
nodes,
|
|
2494
2628
|
edges,
|
|
2495
|
-
subgraphs
|
|
2629
|
+
subgraphs,
|
|
2630
|
+
expand(detailOrFields) {
|
|
2631
|
+
const merged = { ...baseOpts, format: void 0 };
|
|
2632
|
+
if (Array.isArray(detailOrFields)) {
|
|
2633
|
+
merged.fields = detailOrFields;
|
|
2634
|
+
merged.detail = void 0;
|
|
2635
|
+
} else {
|
|
2636
|
+
merged.detail = detailOrFields;
|
|
2637
|
+
merged.fields = void 0;
|
|
2638
|
+
}
|
|
2639
|
+
return graph.describe(merged);
|
|
2640
|
+
}
|
|
2496
2641
|
};
|
|
2497
2642
|
}
|
|
2498
2643
|
_collectSubgraphs(prefix) {
|
|
@@ -2545,14 +2690,15 @@ var Graph = class _Graph {
|
|
|
2545
2690
|
observe(pathOrOpts, options) {
|
|
2546
2691
|
if (typeof pathOrOpts === "string") {
|
|
2547
2692
|
const path = pathOrOpts;
|
|
2548
|
-
const
|
|
2693
|
+
const resolved = resolveObserveDetail(options);
|
|
2694
|
+
const actor2 = resolved.actor;
|
|
2549
2695
|
const target = this.resolve(path);
|
|
2550
2696
|
if (actor2 != null && !target.allowsObserve(actor2)) {
|
|
2551
2697
|
throw new GuardDenied({ actor: actor2, action: "observe", nodeName: path });
|
|
2552
2698
|
}
|
|
2553
|
-
const wantsStructured2 =
|
|
2699
|
+
const wantsStructured2 = resolved.structured === true || resolved.timeline === true || resolved.causal === true || resolved.derived === true || resolved.detail === "minimal" || resolved.detail === "full";
|
|
2554
2700
|
if (wantsStructured2 && _Graph.inspectorEnabled) {
|
|
2555
|
-
return this._createObserveResult(path, target,
|
|
2701
|
+
return this._createObserveResult(path, target, resolved);
|
|
2556
2702
|
}
|
|
2557
2703
|
return {
|
|
2558
2704
|
subscribe(sink) {
|
|
@@ -2568,11 +2714,11 @@ var Graph = class _Graph {
|
|
|
2568
2714
|
}
|
|
2569
2715
|
};
|
|
2570
2716
|
}
|
|
2571
|
-
const opts = pathOrOpts;
|
|
2572
|
-
const actor = opts
|
|
2573
|
-
const wantsStructured = opts
|
|
2717
|
+
const opts = resolveObserveDetail(pathOrOpts);
|
|
2718
|
+
const actor = opts.actor;
|
|
2719
|
+
const wantsStructured = opts.structured === true || opts.timeline === true || opts.causal === true || opts.derived === true || opts.detail === "minimal" || opts.detail === "full";
|
|
2574
2720
|
if (wantsStructured && _Graph.inspectorEnabled) {
|
|
2575
|
-
return this._createObserveResultForAll(opts
|
|
2721
|
+
return this._createObserveResultForAll(opts);
|
|
2576
2722
|
}
|
|
2577
2723
|
return {
|
|
2578
2724
|
subscribe: (sink) => {
|
|
@@ -2604,6 +2750,7 @@ var Graph = class _Graph {
|
|
|
2604
2750
|
const timeline = options.timeline === true;
|
|
2605
2751
|
const causal = options.causal === true;
|
|
2606
2752
|
const derived2 = options.derived === true;
|
|
2753
|
+
const minimal = options.detail === "minimal";
|
|
2607
2754
|
const result = {
|
|
2608
2755
|
values: {},
|
|
2609
2756
|
dirtyCount: 0,
|
|
@@ -2649,6 +2796,11 @@ var Graph = class _Graph {
|
|
|
2649
2796
|
if (t === DATA) {
|
|
2650
2797
|
result.values[path] = m[1];
|
|
2651
2798
|
result.events.push({ type: "data", path, data: m[1], ...base, ...withCausal });
|
|
2799
|
+
} else if (minimal) {
|
|
2800
|
+
if (t === DIRTY) result.dirtyCount++;
|
|
2801
|
+
else if (t === RESOLVED) result.resolvedCount++;
|
|
2802
|
+
else if (t === COMPLETE && !result.errored) result.completedCleanly = true;
|
|
2803
|
+
else if (t === ERROR) result.errored = true;
|
|
2652
2804
|
} else if (t === DIRTY) {
|
|
2653
2805
|
result.dirtyCount++;
|
|
2654
2806
|
result.events.push({ type: "dirty", path, ...base });
|
|
@@ -2664,6 +2816,8 @@ var Graph = class _Graph {
|
|
|
2664
2816
|
}
|
|
2665
2817
|
}
|
|
2666
2818
|
});
|
|
2819
|
+
const graph = this;
|
|
2820
|
+
const basePath = path;
|
|
2667
2821
|
return {
|
|
2668
2822
|
get values() {
|
|
2669
2823
|
return result.values;
|
|
@@ -2686,11 +2840,28 @@ var Graph = class _Graph {
|
|
|
2686
2840
|
dispose() {
|
|
2687
2841
|
unsub();
|
|
2688
2842
|
detachInspectorHook?.();
|
|
2843
|
+
},
|
|
2844
|
+
expand(extra) {
|
|
2845
|
+
unsub();
|
|
2846
|
+
detachInspectorHook?.();
|
|
2847
|
+
const merged = { ...options };
|
|
2848
|
+
if (typeof extra === "string") {
|
|
2849
|
+
merged.detail = extra;
|
|
2850
|
+
} else {
|
|
2851
|
+
Object.assign(merged, extra);
|
|
2852
|
+
}
|
|
2853
|
+
const resolvedTarget = graph.resolve(basePath);
|
|
2854
|
+
return graph._createObserveResult(
|
|
2855
|
+
basePath,
|
|
2856
|
+
resolvedTarget,
|
|
2857
|
+
resolveObserveDetail(merged)
|
|
2858
|
+
);
|
|
2689
2859
|
}
|
|
2690
2860
|
};
|
|
2691
2861
|
}
|
|
2692
2862
|
_createObserveResultForAll(options) {
|
|
2693
2863
|
const timeline = options.timeline === true;
|
|
2864
|
+
const minimal = options.detail === "minimal";
|
|
2694
2865
|
const result = {
|
|
2695
2866
|
values: {},
|
|
2696
2867
|
dirtyCount: 0,
|
|
@@ -2712,6 +2883,11 @@ var Graph = class _Graph {
|
|
|
2712
2883
|
if (t === DATA) {
|
|
2713
2884
|
result.values[path] = m[1];
|
|
2714
2885
|
result.events.push({ type: "data", path, data: m[1], ...base });
|
|
2886
|
+
} else if (minimal) {
|
|
2887
|
+
if (t === DIRTY) result.dirtyCount++;
|
|
2888
|
+
else if (t === RESOLVED) result.resolvedCount++;
|
|
2889
|
+
else if (t === COMPLETE && !result.errored) result.completedCleanly = true;
|
|
2890
|
+
else if (t === ERROR) result.errored = true;
|
|
2715
2891
|
} else if (t === DIRTY) {
|
|
2716
2892
|
result.dirtyCount++;
|
|
2717
2893
|
result.events.push({ type: "dirty", path, ...base });
|
|
@@ -2728,6 +2904,7 @@ var Graph = class _Graph {
|
|
|
2728
2904
|
}
|
|
2729
2905
|
})
|
|
2730
2906
|
);
|
|
2907
|
+
const graph = this;
|
|
2731
2908
|
return {
|
|
2732
2909
|
get values() {
|
|
2733
2910
|
return result.values;
|
|
@@ -2749,6 +2926,16 @@ var Graph = class _Graph {
|
|
|
2749
2926
|
},
|
|
2750
2927
|
dispose() {
|
|
2751
2928
|
for (const u of unsubs) u();
|
|
2929
|
+
},
|
|
2930
|
+
expand(extra) {
|
|
2931
|
+
for (const u of unsubs) u();
|
|
2932
|
+
const merged = { ...options };
|
|
2933
|
+
if (typeof extra === "string") {
|
|
2934
|
+
merged.detail = extra;
|
|
2935
|
+
} else {
|
|
2936
|
+
Object.assign(merged, extra);
|
|
2937
|
+
}
|
|
2938
|
+
return graph._createObserveResultForAll(resolveObserveDetail(merged));
|
|
2752
2939
|
}
|
|
2753
2940
|
};
|
|
2754
2941
|
}
|
|
@@ -2824,6 +3011,9 @@ var Graph = class _Graph {
|
|
|
2824
3011
|
},
|
|
2825
3012
|
dispose() {
|
|
2826
3013
|
stop2();
|
|
3014
|
+
},
|
|
3015
|
+
expand() {
|
|
3016
|
+
throw new Error("expand() requires inspector mode (Graph.inspectorEnabled = true)");
|
|
2827
3017
|
}
|
|
2828
3018
|
};
|
|
2829
3019
|
const pushEvent = (path, message) => {
|
|
@@ -2924,16 +3114,16 @@ var Graph = class _Graph {
|
|
|
2924
3114
|
* @returns Rendered graph text.
|
|
2925
3115
|
*/
|
|
2926
3116
|
dumpGraph(options = {}) {
|
|
2927
|
-
const described = this.describe({
|
|
3117
|
+
const { expand: _, ...described } = this.describe({
|
|
2928
3118
|
actor: options.actor,
|
|
2929
|
-
filter: options.filter
|
|
3119
|
+
filter: options.filter,
|
|
3120
|
+
detail: "standard"
|
|
2930
3121
|
});
|
|
2931
3122
|
const includeEdges = options.includeEdges ?? true;
|
|
2932
3123
|
const includeSubgraphs = options.includeSubgraphs ?? true;
|
|
2933
3124
|
if (options.format === "json") {
|
|
2934
3125
|
const payload = {
|
|
2935
|
-
|
|
2936
|
-
nodes: described.nodes,
|
|
3126
|
+
...described,
|
|
2937
3127
|
edges: includeEdges ? described.edges : [],
|
|
2938
3128
|
subgraphs: includeSubgraphs ? described.subgraphs : []
|
|
2939
3129
|
};
|
|
@@ -3003,10 +3193,11 @@ var Graph = class _Graph {
|
|
|
3003
3193
|
* @returns Persistable snapshot with sorted keys.
|
|
3004
3194
|
*/
|
|
3005
3195
|
snapshot() {
|
|
3006
|
-
const d = this.describe();
|
|
3196
|
+
const { expand: _, ...d } = this.describe({ detail: "full" });
|
|
3007
3197
|
const sortedNodes = {};
|
|
3008
3198
|
for (const key of Object.keys(d.nodes).sort()) {
|
|
3009
|
-
|
|
3199
|
+
const { lastMutation: _lm, guard: _g, ...node2 } = d.nodes[key];
|
|
3200
|
+
sortedNodes[key] = node2;
|
|
3010
3201
|
}
|
|
3011
3202
|
const sortedSubgraphs = [...d.subgraphs].sort();
|
|
3012
3203
|
return { ...d, version: 1, nodes: sortedNodes, subgraphs: sortedSubgraphs };
|
|
@@ -3122,20 +3313,28 @@ var Graph = class _Graph {
|
|
|
3122
3313
|
return g;
|
|
3123
3314
|
}
|
|
3124
3315
|
/**
|
|
3125
|
-
* Plain snapshot with **recursively sorted object keys** for deterministic serialization (§3.8).
|
|
3316
|
+
* Plain snapshot object with **recursively sorted object keys** for deterministic serialization (§3.8).
|
|
3126
3317
|
*
|
|
3127
3318
|
* @remarks
|
|
3128
|
-
* ECMAScript `JSON.stringify(graph)` invokes this method; it must return a plain object, not an
|
|
3129
|
-
* already-stringified JSON string (otherwise the graph would be double-encoded).
|
|
3130
3319
|
* For a single UTF-8 string with a trailing newline (convenient for git), use {@link Graph.toJSONString}.
|
|
3131
3320
|
*
|
|
3132
3321
|
* @returns Same object as {@link Graph.snapshot}.
|
|
3133
3322
|
*/
|
|
3134
|
-
|
|
3323
|
+
toObject() {
|
|
3135
3324
|
return this.snapshot();
|
|
3136
3325
|
}
|
|
3137
3326
|
/**
|
|
3138
|
-
*
|
|
3327
|
+
* ECMAScript `JSON.stringify` hook — delegates to {@link Graph.toObject}.
|
|
3328
|
+
*
|
|
3329
|
+
* @remarks
|
|
3330
|
+
* Must return a plain object (not a string) so `JSON.stringify(graph)` works correctly
|
|
3331
|
+
* without double-encoding.
|
|
3332
|
+
*/
|
|
3333
|
+
toJSON() {
|
|
3334
|
+
return this.toObject();
|
|
3335
|
+
}
|
|
3336
|
+
/**
|
|
3337
|
+
* Deterministic JSON **text**: `JSON.stringify` of {@link Graph.toObject} plus a trailing newline (§3.8).
|
|
3139
3338
|
*
|
|
3140
3339
|
* @returns Stable string suitable for diffs.
|
|
3141
3340
|
*/
|
|
@@ -3160,16 +3359,22 @@ var Graph = class _Graph {
|
|
|
3160
3359
|
if (!pending) return;
|
|
3161
3360
|
pending = false;
|
|
3162
3361
|
try {
|
|
3163
|
-
const
|
|
3362
|
+
const { expand: _expand, ...raw } = this.describe({ detail: "full" });
|
|
3363
|
+
const cleanNodes = {};
|
|
3364
|
+
for (const [p, n] of Object.entries(raw.nodes)) {
|
|
3365
|
+
const { lastMutation: _lm, guard: _g, ...node2 } = n;
|
|
3366
|
+
cleanNodes[p] = node2;
|
|
3367
|
+
}
|
|
3368
|
+
const described = { ...raw, nodes: cleanNodes };
|
|
3164
3369
|
const snapshot = { ...described, version: SNAPSHOT_VERSION };
|
|
3165
3370
|
seq += 1;
|
|
3166
3371
|
const shouldCompact = lastDescribe == null || seq % compactEvery === 0;
|
|
3167
3372
|
if (shouldCompact) {
|
|
3168
|
-
adapter.save({ mode: "full", snapshot, seq });
|
|
3373
|
+
adapter.save(this.name, { mode: "full", snapshot, seq });
|
|
3169
3374
|
} else {
|
|
3170
3375
|
const previous = lastDescribe;
|
|
3171
3376
|
if (previous == null) return;
|
|
3172
|
-
adapter.save({
|
|
3377
|
+
adapter.save(this.name, {
|
|
3173
3378
|
mode: "diff",
|
|
3174
3379
|
diff: _Graph.diff(previous, described),
|
|
3175
3380
|
snapshot,
|
|
@@ -3190,8 +3395,10 @@ var Graph = class _Graph {
|
|
|
3190
3395
|
const triggeredByTier = messages.some((m) => messageTier(m[0]) >= 2);
|
|
3191
3396
|
if (!triggeredByTier) return;
|
|
3192
3397
|
if (options.filter) {
|
|
3193
|
-
const
|
|
3194
|
-
if (
|
|
3398
|
+
const nd = this.resolve(path);
|
|
3399
|
+
if (nd == null) return;
|
|
3400
|
+
const described = describeNode(nd, resolveDescribeFields("standard"));
|
|
3401
|
+
if (!options.filter(path, described)) return;
|
|
3195
3402
|
}
|
|
3196
3403
|
schedule();
|
|
3197
3404
|
});
|