@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
package/dist/graph/index.cjs
CHANGED
|
@@ -159,10 +159,14 @@ function partitionForBatch(messages) {
|
|
|
159
159
|
}
|
|
160
160
|
return { immediate, deferred, terminal };
|
|
161
161
|
}
|
|
162
|
-
function emitWithBatch(emit, messages, phase = 2) {
|
|
162
|
+
function emitWithBatch(emit, messages, phase = 2, options) {
|
|
163
163
|
if (messages.length === 0) {
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
|
+
if (options?.strategy === "sequential") {
|
|
167
|
+
_emitSequential(emit, messages, phase);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
166
170
|
const queue = phase === 3 ? pendingPhase3 : pendingPhase2;
|
|
167
171
|
if (messages.length === 1) {
|
|
168
172
|
const t = messages[0][0];
|
|
@@ -203,6 +207,29 @@ function emitWithBatch(emit, messages, phase = 2) {
|
|
|
203
207
|
}
|
|
204
208
|
}
|
|
205
209
|
}
|
|
210
|
+
function _emitSequential(emit, messages, phase = 2) {
|
|
211
|
+
const dataQueue = phase === 3 ? pendingPhase3 : pendingPhase2;
|
|
212
|
+
for (const msg of messages) {
|
|
213
|
+
const tier = messageTier(msg[0]);
|
|
214
|
+
if (tier === 2) {
|
|
215
|
+
if (isBatching()) {
|
|
216
|
+
const m = msg;
|
|
217
|
+
dataQueue.push(() => emit([m]));
|
|
218
|
+
} else {
|
|
219
|
+
emit([msg]);
|
|
220
|
+
}
|
|
221
|
+
} else if (tier >= 3) {
|
|
222
|
+
if (isBatching()) {
|
|
223
|
+
const m = msg;
|
|
224
|
+
pendingPhase3.push(() => emit([m]));
|
|
225
|
+
} else {
|
|
226
|
+
emit([msg]);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
emit([msg]);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
206
233
|
|
|
207
234
|
// src/core/clock.ts
|
|
208
235
|
function monotonicNs() {
|
|
@@ -311,6 +338,7 @@ function advanceVersion(info, newValue, hashFn) {
|
|
|
311
338
|
}
|
|
312
339
|
|
|
313
340
|
// src/core/node.ts
|
|
341
|
+
var NO_VALUE = /* @__PURE__ */ Symbol.for("graphrefly/NO_VALUE");
|
|
314
342
|
function createIntBitSet() {
|
|
315
343
|
let bits = 0;
|
|
316
344
|
return {
|
|
@@ -440,10 +468,10 @@ var NodeImpl = class {
|
|
|
440
468
|
this._hasDeps = deps.length > 0;
|
|
441
469
|
this._autoComplete = opts.completeWhenDepsComplete ?? true;
|
|
442
470
|
this._isSingleDep = deps.length === 1 && fn != null;
|
|
443
|
-
this._cached = opts.initial;
|
|
471
|
+
this._cached = "initial" in opts ? opts.initial : NO_VALUE;
|
|
444
472
|
this._status = this._hasDeps ? "disconnected" : "settled";
|
|
445
473
|
this._hashFn = opts.versioningHash ?? defaultHash;
|
|
446
|
-
this._versioning = opts.versioning != null ? createVersioning(opts.versioning, this._cached, {
|
|
474
|
+
this._versioning = opts.versioning != null ? createVersioning(opts.versioning, this._cached === NO_VALUE ? void 0 : this._cached, {
|
|
447
475
|
id: opts.versioningId,
|
|
448
476
|
hash: this._hashFn
|
|
449
477
|
}) : void 0;
|
|
@@ -527,10 +555,14 @@ var NodeImpl = class {
|
|
|
527
555
|
_applyVersioning(level, opts) {
|
|
528
556
|
if (this._versioning != null) return;
|
|
529
557
|
this._hashFn = opts?.hash ?? this._hashFn;
|
|
530
|
-
this._versioning = createVersioning(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
558
|
+
this._versioning = createVersioning(
|
|
559
|
+
level,
|
|
560
|
+
this._cached === NO_VALUE ? void 0 : this._cached,
|
|
561
|
+
{
|
|
562
|
+
id: opts?.id,
|
|
563
|
+
hash: this._hashFn
|
|
564
|
+
}
|
|
565
|
+
);
|
|
534
566
|
}
|
|
535
567
|
hasGuard() {
|
|
536
568
|
return this._guard != null;
|
|
@@ -540,7 +572,7 @@ var NodeImpl = class {
|
|
|
540
572
|
return this._guard(normalizeActor(actor), "observe");
|
|
541
573
|
}
|
|
542
574
|
get() {
|
|
543
|
-
return this._cached;
|
|
575
|
+
return this._cached === NO_VALUE ? void 0 : this._cached;
|
|
544
576
|
}
|
|
545
577
|
down(messages, options) {
|
|
546
578
|
if (messages.length === 0) return;
|
|
@@ -597,6 +629,7 @@ var NodeImpl = class {
|
|
|
597
629
|
}
|
|
598
630
|
if (this._terminal && this._opts.resubscribable) {
|
|
599
631
|
this._terminal = false;
|
|
632
|
+
this._cached = NO_VALUE;
|
|
600
633
|
this._status = this._hasDeps ? "disconnected" : "settled";
|
|
601
634
|
this._opts.onResubscribe?.();
|
|
602
635
|
}
|
|
@@ -696,7 +729,7 @@ var NodeImpl = class {
|
|
|
696
729
|
const cleanupFn = this._cleanup;
|
|
697
730
|
this._cleanup = void 0;
|
|
698
731
|
cleanupFn?.();
|
|
699
|
-
this._cached =
|
|
732
|
+
this._cached = NO_VALUE;
|
|
700
733
|
this._lastDepValues = void 0;
|
|
701
734
|
}
|
|
702
735
|
this._status = statusAfterMessage(this._status, m);
|
|
@@ -705,7 +738,7 @@ var NodeImpl = class {
|
|
|
705
738
|
}
|
|
706
739
|
if (t === TEARDOWN) {
|
|
707
740
|
if (this._opts.resetOnTeardown) {
|
|
708
|
-
this._cached =
|
|
741
|
+
this._cached = NO_VALUE;
|
|
709
742
|
}
|
|
710
743
|
const teardownCleanup = this._cleanup;
|
|
711
744
|
this._cleanup = void 0;
|
|
@@ -736,7 +769,15 @@ var NodeImpl = class {
|
|
|
736
769
|
}
|
|
737
770
|
_emitAutoValue(value) {
|
|
738
771
|
const wasDirty = this._status === "dirty";
|
|
739
|
-
|
|
772
|
+
let unchanged;
|
|
773
|
+
try {
|
|
774
|
+
unchanged = this._cached !== NO_VALUE && this._equals(this._cached, value);
|
|
775
|
+
} catch (eqErr) {
|
|
776
|
+
const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
|
|
777
|
+
const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
|
|
778
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
740
781
|
if (unchanged) {
|
|
741
782
|
this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
|
|
742
783
|
return;
|
|
@@ -783,7 +824,9 @@ var NodeImpl = class {
|
|
|
783
824
|
if (out === void 0) return;
|
|
784
825
|
this._emitAutoValue(out);
|
|
785
826
|
} catch (err) {
|
|
786
|
-
|
|
827
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
828
|
+
const wrapped = new Error(`Node "${this.name}": fn threw: ${errMsg}`, { cause: err });
|
|
829
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
787
830
|
}
|
|
788
831
|
}
|
|
789
832
|
_onDepDirty(index) {
|
|
@@ -818,7 +861,11 @@ var NodeImpl = class {
|
|
|
818
861
|
try {
|
|
819
862
|
if (this._onMessage(msg, index, this._actions)) continue;
|
|
820
863
|
} catch (err) {
|
|
821
|
-
|
|
864
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
865
|
+
const wrapped = new Error(`Node "${this.name}": onMessage threw: ${errMsg}`, {
|
|
866
|
+
cause: err
|
|
867
|
+
});
|
|
868
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
822
869
|
return;
|
|
823
870
|
}
|
|
824
871
|
}
|
|
@@ -951,7 +998,7 @@ var DynamicNodeImpl = class {
|
|
|
951
998
|
_actions;
|
|
952
999
|
_boundEmitToSinks;
|
|
953
1000
|
// Mutable state
|
|
954
|
-
_cached;
|
|
1001
|
+
_cached = NO_VALUE;
|
|
955
1002
|
_status = "disconnected";
|
|
956
1003
|
_terminal = false;
|
|
957
1004
|
_connected = false;
|
|
@@ -1045,7 +1092,7 @@ var DynamicNodeImpl = class {
|
|
|
1045
1092
|
return this._guard(normalizeActor(actor), "observe");
|
|
1046
1093
|
}
|
|
1047
1094
|
get() {
|
|
1048
|
-
return this._cached;
|
|
1095
|
+
return this._cached === NO_VALUE ? void 0 : this._cached;
|
|
1049
1096
|
}
|
|
1050
1097
|
down(messages, options) {
|
|
1051
1098
|
if (messages.length === 0) return;
|
|
@@ -1103,6 +1150,7 @@ var DynamicNodeImpl = class {
|
|
|
1103
1150
|
}
|
|
1104
1151
|
if (this._terminal && this._resubscribable) {
|
|
1105
1152
|
this._terminal = false;
|
|
1153
|
+
this._cached = NO_VALUE;
|
|
1106
1154
|
this._status = "disconnected";
|
|
1107
1155
|
this._onResubscribe?.();
|
|
1108
1156
|
}
|
|
@@ -1180,10 +1228,13 @@ var DynamicNodeImpl = class {
|
|
|
1180
1228
|
const t = m[0];
|
|
1181
1229
|
if (t === DATA) this._cached = m[1];
|
|
1182
1230
|
if (t === INVALIDATE) {
|
|
1183
|
-
this._cached =
|
|
1231
|
+
this._cached = NO_VALUE;
|
|
1232
|
+
this._status = "dirty";
|
|
1184
1233
|
}
|
|
1185
|
-
if (t === DATA
|
|
1234
|
+
if (t === DATA) {
|
|
1186
1235
|
this._status = "settled";
|
|
1236
|
+
} else if (t === RESOLVED) {
|
|
1237
|
+
this._status = "resolved";
|
|
1187
1238
|
} else if (t === DIRTY) {
|
|
1188
1239
|
this._status = "dirty";
|
|
1189
1240
|
} else if (t === COMPLETE) {
|
|
@@ -1194,7 +1245,7 @@ var DynamicNodeImpl = class {
|
|
|
1194
1245
|
this._terminal = true;
|
|
1195
1246
|
}
|
|
1196
1247
|
if (t === TEARDOWN) {
|
|
1197
|
-
if (this._resetOnTeardown) this._cached =
|
|
1248
|
+
if (this._resetOnTeardown) this._cached = NO_VALUE;
|
|
1198
1249
|
try {
|
|
1199
1250
|
this._propagateToMeta(t);
|
|
1200
1251
|
} finally {
|
|
@@ -1217,7 +1268,15 @@ var DynamicNodeImpl = class {
|
|
|
1217
1268
|
}
|
|
1218
1269
|
_emitAutoValue(value) {
|
|
1219
1270
|
const wasDirty = this._status === "dirty";
|
|
1220
|
-
|
|
1271
|
+
let unchanged;
|
|
1272
|
+
try {
|
|
1273
|
+
unchanged = this._cached !== NO_VALUE && this._equals(this._cached, value);
|
|
1274
|
+
} catch (eqErr) {
|
|
1275
|
+
const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
|
|
1276
|
+
const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
|
|
1277
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1221
1280
|
if (unchanged) {
|
|
1222
1281
|
this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
|
|
1223
1282
|
return;
|
|
@@ -1383,6 +1442,19 @@ var DynamicNodeImpl = class {
|
|
|
1383
1442
|
};
|
|
1384
1443
|
|
|
1385
1444
|
// src/core/meta.ts
|
|
1445
|
+
function resolveDescribeFields(detail, fields) {
|
|
1446
|
+
if (fields != null && fields.length > 0) return new Set(fields);
|
|
1447
|
+
switch (detail) {
|
|
1448
|
+
case "standard":
|
|
1449
|
+
return /* @__PURE__ */ new Set(["type", "status", "value", "deps", "meta", "v"]);
|
|
1450
|
+
case "full":
|
|
1451
|
+
return null;
|
|
1452
|
+
// null = include everything
|
|
1453
|
+
case "minimal":
|
|
1454
|
+
default:
|
|
1455
|
+
return /* @__PURE__ */ new Set(["type", "deps"]);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1386
1458
|
function inferDescribeType(n) {
|
|
1387
1459
|
if (n._describeKind != null) return n._describeKind;
|
|
1388
1460
|
if (!n._hasDeps) return n._fn != null ? "producer" : "state";
|
|
@@ -1400,12 +1472,10 @@ function metaSnapshot(node2) {
|
|
|
1400
1472
|
}
|
|
1401
1473
|
return out;
|
|
1402
1474
|
}
|
|
1403
|
-
function describeNode(node2) {
|
|
1404
|
-
const
|
|
1405
|
-
const
|
|
1406
|
-
|
|
1407
|
-
meta.access = accessHintForGuard(guard);
|
|
1408
|
-
}
|
|
1475
|
+
function describeNode(node2, includeFields) {
|
|
1476
|
+
const all = includeFields == null;
|
|
1477
|
+
const metaKeys = !all && includeFields != null ? [...includeFields].filter((f) => f.startsWith("meta.")).map((f) => f.slice(5)) : null;
|
|
1478
|
+
const wantsMeta = all || includeFields.has("meta") || metaKeys != null && metaKeys.length > 0;
|
|
1409
1479
|
let type = "state";
|
|
1410
1480
|
let deps = [];
|
|
1411
1481
|
if (node2 instanceof NodeImpl) {
|
|
@@ -1415,20 +1485,36 @@ function describeNode(node2) {
|
|
|
1415
1485
|
type = node2._describeKind ?? "derived";
|
|
1416
1486
|
deps = [];
|
|
1417
1487
|
}
|
|
1418
|
-
const out = {
|
|
1419
|
-
|
|
1420
|
-
status
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1488
|
+
const out = { type, deps };
|
|
1489
|
+
if (all || includeFields.has("status")) {
|
|
1490
|
+
out.status = node2.status;
|
|
1491
|
+
}
|
|
1492
|
+
const guard = node2 instanceof NodeImpl && node2._guard || node2 instanceof DynamicNodeImpl && node2._guard || void 0;
|
|
1493
|
+
if (wantsMeta) {
|
|
1494
|
+
const rawMeta = { ...metaSnapshot(node2) };
|
|
1495
|
+
if (guard != null && rawMeta.access === void 0) {
|
|
1496
|
+
rawMeta.access = accessHintForGuard(guard);
|
|
1497
|
+
}
|
|
1498
|
+
if (metaKeys != null && metaKeys.length > 0 && !includeFields.has("meta")) {
|
|
1499
|
+
const filtered = {};
|
|
1500
|
+
for (const k of metaKeys) {
|
|
1501
|
+
if (k in rawMeta) filtered[k] = rawMeta[k];
|
|
1502
|
+
}
|
|
1503
|
+
out.meta = filtered;
|
|
1504
|
+
} else {
|
|
1505
|
+
out.meta = rawMeta;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1424
1508
|
if (node2.name != null) {
|
|
1425
1509
|
out.name = node2.name;
|
|
1426
1510
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1511
|
+
if (all || includeFields.has("value")) {
|
|
1512
|
+
try {
|
|
1513
|
+
out.value = node2.get();
|
|
1514
|
+
} catch {
|
|
1515
|
+
}
|
|
1430
1516
|
}
|
|
1431
|
-
if (node2.v != null) {
|
|
1517
|
+
if ((all || includeFields.has("v")) && node2.v != null) {
|
|
1432
1518
|
const vInfo = { id: node2.v.id, version: node2.v.version };
|
|
1433
1519
|
if ("cid" in node2.v) {
|
|
1434
1520
|
vInfo.cid = node2.v.cid;
|
|
@@ -1436,6 +1522,16 @@ function describeNode(node2) {
|
|
|
1436
1522
|
}
|
|
1437
1523
|
out.v = vInfo;
|
|
1438
1524
|
}
|
|
1525
|
+
if (all || includeFields.has("guard")) {
|
|
1526
|
+
if (guard != null) {
|
|
1527
|
+
out.guard = accessHintForGuard(guard);
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
if (all || includeFields.has("lastMutation")) {
|
|
1531
|
+
if (node2.lastMutation != null) {
|
|
1532
|
+
out.lastMutation = node2.lastMutation;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1439
1535
|
return out;
|
|
1440
1536
|
}
|
|
1441
1537
|
|
|
@@ -1630,6 +1726,23 @@ function resolveSpyTheme(theme) {
|
|
|
1630
1726
|
reset: theme.reset ?? ""
|
|
1631
1727
|
};
|
|
1632
1728
|
}
|
|
1729
|
+
function resolveObserveDetail(opts) {
|
|
1730
|
+
if (opts == null) return {};
|
|
1731
|
+
const detail = opts.detail;
|
|
1732
|
+
if (detail === "full") {
|
|
1733
|
+
return {
|
|
1734
|
+
...opts,
|
|
1735
|
+
structured: opts.structured ?? true,
|
|
1736
|
+
timeline: opts.timeline ?? true,
|
|
1737
|
+
causal: opts.causal ?? true,
|
|
1738
|
+
derived: opts.derived ?? true
|
|
1739
|
+
};
|
|
1740
|
+
}
|
|
1741
|
+
if (detail === "minimal") {
|
|
1742
|
+
return { ...opts, structured: opts.structured ?? true };
|
|
1743
|
+
}
|
|
1744
|
+
return opts;
|
|
1745
|
+
}
|
|
1633
1746
|
function assertLocalName(name, graphName, label) {
|
|
1634
1747
|
if (name === "") {
|
|
1635
1748
|
throw new Error(`Graph "${graphName}": ${label} name must be non-empty`);
|
|
@@ -1827,6 +1940,22 @@ var Graph = class _Graph {
|
|
|
1827
1940
|
if (this._defaultVersioningLevel != null) {
|
|
1828
1941
|
node2._applyVersioning(this._defaultVersioningLevel);
|
|
1829
1942
|
}
|
|
1943
|
+
if (node2._deps.length > 0) {
|
|
1944
|
+
for (const dep of node2._deps) {
|
|
1945
|
+
for (const [depName, depNode] of this._nodes) {
|
|
1946
|
+
if (depNode === dep) {
|
|
1947
|
+
this._edges.add(edgeKey(depName, name));
|
|
1948
|
+
break;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
for (const [otherName, otherNode] of this._nodes) {
|
|
1954
|
+
if (otherName === name) continue;
|
|
1955
|
+
if (otherNode instanceof NodeImpl && otherNode._deps.includes(node2)) {
|
|
1956
|
+
this._edges.add(edgeKey(name, otherName));
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1830
1959
|
}
|
|
1831
1960
|
}
|
|
1832
1961
|
/**
|
|
@@ -2213,6 +2342,9 @@ var Graph = class _Graph {
|
|
|
2213
2342
|
describe(options) {
|
|
2214
2343
|
const actor = options?.actor;
|
|
2215
2344
|
const filter = options?.filter;
|
|
2345
|
+
const includeFields = resolveDescribeFields(options?.detail, options?.fields);
|
|
2346
|
+
const isSpec = options?.format === "spec";
|
|
2347
|
+
const effectiveFields = isSpec ? resolveDescribeFields("minimal") : includeFields;
|
|
2216
2348
|
const targets = [];
|
|
2217
2349
|
this._collectObserveTargets("", targets);
|
|
2218
2350
|
const nodeToPath = /* @__PURE__ */ new Map();
|
|
@@ -2222,7 +2354,7 @@ var Graph = class _Graph {
|
|
|
2222
2354
|
const nodes = {};
|
|
2223
2355
|
for (const [p, n] of targets) {
|
|
2224
2356
|
if (actor != null && !n.allowsObserve(actor)) continue;
|
|
2225
|
-
const raw = describeNode(n);
|
|
2357
|
+
const raw = describeNode(n, effectiveFields);
|
|
2226
2358
|
const deps = n instanceof NodeImpl ? n._deps.map((d) => nodeToPath.get(d) ?? d.name ?? "") : [];
|
|
2227
2359
|
const { name: _name, ...rest } = raw;
|
|
2228
2360
|
const entry = { ...rest, deps };
|
|
@@ -2243,7 +2375,7 @@ var Graph = class _Graph {
|
|
|
2243
2375
|
continue;
|
|
2244
2376
|
}
|
|
2245
2377
|
if (normalizedKey === "metaHas") {
|
|
2246
|
-
if (!Object.hasOwn(entry.meta, String(fv))) {
|
|
2378
|
+
if (!Object.hasOwn(entry.meta ?? {}, String(fv))) {
|
|
2247
2379
|
match = false;
|
|
2248
2380
|
break;
|
|
2249
2381
|
}
|
|
@@ -2276,11 +2408,24 @@ var Graph = class _Graph {
|
|
|
2276
2408
|
const prefix = `${sg}${PATH_SEP}`;
|
|
2277
2409
|
return [...nodeKeys].some((k) => k === sg || k.startsWith(prefix));
|
|
2278
2410
|
}) : allSubgraphs;
|
|
2411
|
+
const graph = this;
|
|
2412
|
+
const baseOpts = options;
|
|
2279
2413
|
return {
|
|
2280
2414
|
name: this.name,
|
|
2281
2415
|
nodes,
|
|
2282
2416
|
edges,
|
|
2283
|
-
subgraphs
|
|
2417
|
+
subgraphs,
|
|
2418
|
+
expand(detailOrFields) {
|
|
2419
|
+
const merged = { ...baseOpts, format: void 0 };
|
|
2420
|
+
if (Array.isArray(detailOrFields)) {
|
|
2421
|
+
merged.fields = detailOrFields;
|
|
2422
|
+
merged.detail = void 0;
|
|
2423
|
+
} else {
|
|
2424
|
+
merged.detail = detailOrFields;
|
|
2425
|
+
merged.fields = void 0;
|
|
2426
|
+
}
|
|
2427
|
+
return graph.describe(merged);
|
|
2428
|
+
}
|
|
2284
2429
|
};
|
|
2285
2430
|
}
|
|
2286
2431
|
_collectSubgraphs(prefix) {
|
|
@@ -2333,14 +2478,15 @@ var Graph = class _Graph {
|
|
|
2333
2478
|
observe(pathOrOpts, options) {
|
|
2334
2479
|
if (typeof pathOrOpts === "string") {
|
|
2335
2480
|
const path = pathOrOpts;
|
|
2336
|
-
const
|
|
2481
|
+
const resolved = resolveObserveDetail(options);
|
|
2482
|
+
const actor2 = resolved.actor;
|
|
2337
2483
|
const target = this.resolve(path);
|
|
2338
2484
|
if (actor2 != null && !target.allowsObserve(actor2)) {
|
|
2339
2485
|
throw new GuardDenied({ actor: actor2, action: "observe", nodeName: path });
|
|
2340
2486
|
}
|
|
2341
|
-
const wantsStructured2 =
|
|
2487
|
+
const wantsStructured2 = resolved.structured === true || resolved.timeline === true || resolved.causal === true || resolved.derived === true || resolved.detail === "minimal" || resolved.detail === "full";
|
|
2342
2488
|
if (wantsStructured2 && _Graph.inspectorEnabled) {
|
|
2343
|
-
return this._createObserveResult(path, target,
|
|
2489
|
+
return this._createObserveResult(path, target, resolved);
|
|
2344
2490
|
}
|
|
2345
2491
|
return {
|
|
2346
2492
|
subscribe(sink) {
|
|
@@ -2356,11 +2502,11 @@ var Graph = class _Graph {
|
|
|
2356
2502
|
}
|
|
2357
2503
|
};
|
|
2358
2504
|
}
|
|
2359
|
-
const opts = pathOrOpts;
|
|
2360
|
-
const actor = opts
|
|
2361
|
-
const wantsStructured = opts
|
|
2505
|
+
const opts = resolveObserveDetail(pathOrOpts);
|
|
2506
|
+
const actor = opts.actor;
|
|
2507
|
+
const wantsStructured = opts.structured === true || opts.timeline === true || opts.causal === true || opts.derived === true || opts.detail === "minimal" || opts.detail === "full";
|
|
2362
2508
|
if (wantsStructured && _Graph.inspectorEnabled) {
|
|
2363
|
-
return this._createObserveResultForAll(opts
|
|
2509
|
+
return this._createObserveResultForAll(opts);
|
|
2364
2510
|
}
|
|
2365
2511
|
return {
|
|
2366
2512
|
subscribe: (sink) => {
|
|
@@ -2392,6 +2538,7 @@ var Graph = class _Graph {
|
|
|
2392
2538
|
const timeline = options.timeline === true;
|
|
2393
2539
|
const causal = options.causal === true;
|
|
2394
2540
|
const derived = options.derived === true;
|
|
2541
|
+
const minimal = options.detail === "minimal";
|
|
2395
2542
|
const result = {
|
|
2396
2543
|
values: {},
|
|
2397
2544
|
dirtyCount: 0,
|
|
@@ -2437,6 +2584,11 @@ var Graph = class _Graph {
|
|
|
2437
2584
|
if (t === DATA) {
|
|
2438
2585
|
result.values[path] = m[1];
|
|
2439
2586
|
result.events.push({ type: "data", path, data: m[1], ...base, ...withCausal });
|
|
2587
|
+
} else if (minimal) {
|
|
2588
|
+
if (t === DIRTY) result.dirtyCount++;
|
|
2589
|
+
else if (t === RESOLVED) result.resolvedCount++;
|
|
2590
|
+
else if (t === COMPLETE && !result.errored) result.completedCleanly = true;
|
|
2591
|
+
else if (t === ERROR) result.errored = true;
|
|
2440
2592
|
} else if (t === DIRTY) {
|
|
2441
2593
|
result.dirtyCount++;
|
|
2442
2594
|
result.events.push({ type: "dirty", path, ...base });
|
|
@@ -2452,6 +2604,8 @@ var Graph = class _Graph {
|
|
|
2452
2604
|
}
|
|
2453
2605
|
}
|
|
2454
2606
|
});
|
|
2607
|
+
const graph = this;
|
|
2608
|
+
const basePath = path;
|
|
2455
2609
|
return {
|
|
2456
2610
|
get values() {
|
|
2457
2611
|
return result.values;
|
|
@@ -2474,11 +2628,28 @@ var Graph = class _Graph {
|
|
|
2474
2628
|
dispose() {
|
|
2475
2629
|
unsub();
|
|
2476
2630
|
detachInspectorHook?.();
|
|
2631
|
+
},
|
|
2632
|
+
expand(extra) {
|
|
2633
|
+
unsub();
|
|
2634
|
+
detachInspectorHook?.();
|
|
2635
|
+
const merged = { ...options };
|
|
2636
|
+
if (typeof extra === "string") {
|
|
2637
|
+
merged.detail = extra;
|
|
2638
|
+
} else {
|
|
2639
|
+
Object.assign(merged, extra);
|
|
2640
|
+
}
|
|
2641
|
+
const resolvedTarget = graph.resolve(basePath);
|
|
2642
|
+
return graph._createObserveResult(
|
|
2643
|
+
basePath,
|
|
2644
|
+
resolvedTarget,
|
|
2645
|
+
resolveObserveDetail(merged)
|
|
2646
|
+
);
|
|
2477
2647
|
}
|
|
2478
2648
|
};
|
|
2479
2649
|
}
|
|
2480
2650
|
_createObserveResultForAll(options) {
|
|
2481
2651
|
const timeline = options.timeline === true;
|
|
2652
|
+
const minimal = options.detail === "minimal";
|
|
2482
2653
|
const result = {
|
|
2483
2654
|
values: {},
|
|
2484
2655
|
dirtyCount: 0,
|
|
@@ -2500,6 +2671,11 @@ var Graph = class _Graph {
|
|
|
2500
2671
|
if (t === DATA) {
|
|
2501
2672
|
result.values[path] = m[1];
|
|
2502
2673
|
result.events.push({ type: "data", path, data: m[1], ...base });
|
|
2674
|
+
} else if (minimal) {
|
|
2675
|
+
if (t === DIRTY) result.dirtyCount++;
|
|
2676
|
+
else if (t === RESOLVED) result.resolvedCount++;
|
|
2677
|
+
else if (t === COMPLETE && !result.errored) result.completedCleanly = true;
|
|
2678
|
+
else if (t === ERROR) result.errored = true;
|
|
2503
2679
|
} else if (t === DIRTY) {
|
|
2504
2680
|
result.dirtyCount++;
|
|
2505
2681
|
result.events.push({ type: "dirty", path, ...base });
|
|
@@ -2516,6 +2692,7 @@ var Graph = class _Graph {
|
|
|
2516
2692
|
}
|
|
2517
2693
|
})
|
|
2518
2694
|
);
|
|
2695
|
+
const graph = this;
|
|
2519
2696
|
return {
|
|
2520
2697
|
get values() {
|
|
2521
2698
|
return result.values;
|
|
@@ -2537,6 +2714,16 @@ var Graph = class _Graph {
|
|
|
2537
2714
|
},
|
|
2538
2715
|
dispose() {
|
|
2539
2716
|
for (const u of unsubs) u();
|
|
2717
|
+
},
|
|
2718
|
+
expand(extra) {
|
|
2719
|
+
for (const u of unsubs) u();
|
|
2720
|
+
const merged = { ...options };
|
|
2721
|
+
if (typeof extra === "string") {
|
|
2722
|
+
merged.detail = extra;
|
|
2723
|
+
} else {
|
|
2724
|
+
Object.assign(merged, extra);
|
|
2725
|
+
}
|
|
2726
|
+
return graph._createObserveResultForAll(resolveObserveDetail(merged));
|
|
2540
2727
|
}
|
|
2541
2728
|
};
|
|
2542
2729
|
}
|
|
@@ -2612,6 +2799,9 @@ var Graph = class _Graph {
|
|
|
2612
2799
|
},
|
|
2613
2800
|
dispose() {
|
|
2614
2801
|
stop2();
|
|
2802
|
+
},
|
|
2803
|
+
expand() {
|
|
2804
|
+
throw new Error("expand() requires inspector mode (Graph.inspectorEnabled = true)");
|
|
2615
2805
|
}
|
|
2616
2806
|
};
|
|
2617
2807
|
const pushEvent = (path, message) => {
|
|
@@ -2712,16 +2902,16 @@ var Graph = class _Graph {
|
|
|
2712
2902
|
* @returns Rendered graph text.
|
|
2713
2903
|
*/
|
|
2714
2904
|
dumpGraph(options = {}) {
|
|
2715
|
-
const described = this.describe({
|
|
2905
|
+
const { expand: _, ...described } = this.describe({
|
|
2716
2906
|
actor: options.actor,
|
|
2717
|
-
filter: options.filter
|
|
2907
|
+
filter: options.filter,
|
|
2908
|
+
detail: "standard"
|
|
2718
2909
|
});
|
|
2719
2910
|
const includeEdges = options.includeEdges ?? true;
|
|
2720
2911
|
const includeSubgraphs = options.includeSubgraphs ?? true;
|
|
2721
2912
|
if (options.format === "json") {
|
|
2722
2913
|
const payload = {
|
|
2723
|
-
|
|
2724
|
-
nodes: described.nodes,
|
|
2914
|
+
...described,
|
|
2725
2915
|
edges: includeEdges ? described.edges : [],
|
|
2726
2916
|
subgraphs: includeSubgraphs ? described.subgraphs : []
|
|
2727
2917
|
};
|
|
@@ -2791,10 +2981,11 @@ var Graph = class _Graph {
|
|
|
2791
2981
|
* @returns Persistable snapshot with sorted keys.
|
|
2792
2982
|
*/
|
|
2793
2983
|
snapshot() {
|
|
2794
|
-
const d = this.describe();
|
|
2984
|
+
const { expand: _, ...d } = this.describe({ detail: "full" });
|
|
2795
2985
|
const sortedNodes = {};
|
|
2796
2986
|
for (const key of Object.keys(d.nodes).sort()) {
|
|
2797
|
-
|
|
2987
|
+
const { lastMutation: _lm, guard: _g, ...node2 } = d.nodes[key];
|
|
2988
|
+
sortedNodes[key] = node2;
|
|
2798
2989
|
}
|
|
2799
2990
|
const sortedSubgraphs = [...d.subgraphs].sort();
|
|
2800
2991
|
return { ...d, version: 1, nodes: sortedNodes, subgraphs: sortedSubgraphs };
|
|
@@ -2910,20 +3101,28 @@ var Graph = class _Graph {
|
|
|
2910
3101
|
return g;
|
|
2911
3102
|
}
|
|
2912
3103
|
/**
|
|
2913
|
-
* Plain snapshot with **recursively sorted object keys** for deterministic serialization (§3.8).
|
|
3104
|
+
* Plain snapshot object with **recursively sorted object keys** for deterministic serialization (§3.8).
|
|
2914
3105
|
*
|
|
2915
3106
|
* @remarks
|
|
2916
|
-
* ECMAScript `JSON.stringify(graph)` invokes this method; it must return a plain object, not an
|
|
2917
|
-
* already-stringified JSON string (otherwise the graph would be double-encoded).
|
|
2918
3107
|
* For a single UTF-8 string with a trailing newline (convenient for git), use {@link Graph.toJSONString}.
|
|
2919
3108
|
*
|
|
2920
3109
|
* @returns Same object as {@link Graph.snapshot}.
|
|
2921
3110
|
*/
|
|
2922
|
-
|
|
3111
|
+
toObject() {
|
|
2923
3112
|
return this.snapshot();
|
|
2924
3113
|
}
|
|
2925
3114
|
/**
|
|
2926
|
-
*
|
|
3115
|
+
* ECMAScript `JSON.stringify` hook — delegates to {@link Graph.toObject}.
|
|
3116
|
+
*
|
|
3117
|
+
* @remarks
|
|
3118
|
+
* Must return a plain object (not a string) so `JSON.stringify(graph)` works correctly
|
|
3119
|
+
* without double-encoding.
|
|
3120
|
+
*/
|
|
3121
|
+
toJSON() {
|
|
3122
|
+
return this.toObject();
|
|
3123
|
+
}
|
|
3124
|
+
/**
|
|
3125
|
+
* Deterministic JSON **text**: `JSON.stringify` of {@link Graph.toObject} plus a trailing newline (§3.8).
|
|
2927
3126
|
*
|
|
2928
3127
|
* @returns Stable string suitable for diffs.
|
|
2929
3128
|
*/
|
|
@@ -2948,16 +3147,22 @@ var Graph = class _Graph {
|
|
|
2948
3147
|
if (!pending) return;
|
|
2949
3148
|
pending = false;
|
|
2950
3149
|
try {
|
|
2951
|
-
const
|
|
3150
|
+
const { expand: _expand, ...raw } = this.describe({ detail: "full" });
|
|
3151
|
+
const cleanNodes = {};
|
|
3152
|
+
for (const [p, n] of Object.entries(raw.nodes)) {
|
|
3153
|
+
const { lastMutation: _lm, guard: _g, ...node2 } = n;
|
|
3154
|
+
cleanNodes[p] = node2;
|
|
3155
|
+
}
|
|
3156
|
+
const described = { ...raw, nodes: cleanNodes };
|
|
2952
3157
|
const snapshot = { ...described, version: SNAPSHOT_VERSION };
|
|
2953
3158
|
seq += 1;
|
|
2954
3159
|
const shouldCompact = lastDescribe == null || seq % compactEvery === 0;
|
|
2955
3160
|
if (shouldCompact) {
|
|
2956
|
-
adapter.save({ mode: "full", snapshot, seq });
|
|
3161
|
+
adapter.save(this.name, { mode: "full", snapshot, seq });
|
|
2957
3162
|
} else {
|
|
2958
3163
|
const previous = lastDescribe;
|
|
2959
3164
|
if (previous == null) return;
|
|
2960
|
-
adapter.save({
|
|
3165
|
+
adapter.save(this.name, {
|
|
2961
3166
|
mode: "diff",
|
|
2962
3167
|
diff: _Graph.diff(previous, described),
|
|
2963
3168
|
snapshot,
|
|
@@ -2978,8 +3183,10 @@ var Graph = class _Graph {
|
|
|
2978
3183
|
const triggeredByTier = messages.some((m) => messageTier(m[0]) >= 2);
|
|
2979
3184
|
if (!triggeredByTier) return;
|
|
2980
3185
|
if (options.filter) {
|
|
2981
|
-
const
|
|
2982
|
-
if (
|
|
3186
|
+
const nd = this.resolve(path);
|
|
3187
|
+
if (nd == null) return;
|
|
3188
|
+
const described = describeNode(nd, resolveDescribeFields("standard"));
|
|
3189
|
+
if (!options.filter(path, described)) return;
|
|
2983
3190
|
}
|
|
2984
3191
|
schedule();
|
|
2985
3192
|
});
|