@graphrefly/graphrefly 0.22.0 → 0.24.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/dist/{chunk-QA3RP5NH.js → chunk-5DJTTKX3.js} +111 -17
- package/dist/chunk-5DJTTKX3.js.map +1 -0
- package/dist/{chunk-BLD3IFYF.js → chunk-5WGT55R4.js} +9 -7
- package/dist/{chunk-BLD3IFYF.js.map → chunk-5WGT55R4.js.map} +1 -1
- package/dist/{chunk-IR3KMOLX.js → chunk-AOCBDH4T.js} +3 -383
- package/dist/chunk-AOCBDH4T.js.map +1 -0
- package/dist/{chunk-TH6COGOP.js → chunk-H4RVA4VE.js} +2 -2
- package/dist/chunk-HWPIFSW2.js +36 -0
- package/dist/chunk-HWPIFSW2.js.map +1 -0
- package/dist/{chunk-MQBQOFDS.js → chunk-IPLKX3L2.js} +12 -31
- package/dist/chunk-IPLKX3L2.js.map +1 -0
- package/dist/{chunk-44HD4BTA.js → chunk-MW4VAKAO.js} +3 -3
- package/dist/chunk-PY4XCDLR.js +391 -0
- package/dist/chunk-PY4XCDLR.js.map +1 -0
- package/dist/{chunk-RHI3GHZW.js → chunk-QOWVNWOC.js} +3 -3
- package/dist/{chunk-EQUZ5NLD.js → chunk-TDEXAMGO.js} +11 -16
- package/dist/chunk-TDEXAMGO.js.map +1 -0
- package/dist/{chunk-NXC35KC5.js → chunk-XOFWRC73.js} +3 -3
- package/dist/compat/nestjs/index.cjs +110 -16
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +6 -6
- package/dist/compat/nestjs/index.d.ts +6 -6
- package/dist/compat/nestjs/index.js +9 -7
- package/dist/core/index.cjs +110 -16
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/extra/index.cjs +110 -16
- 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 +9 -7
- package/dist/graph/index.cjs +110 -16
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +5 -5
- package/dist/graph/index.d.ts +5 -5
- package/dist/graph/index.js +4 -4
- package/dist/{graph-DFr0diXB.d.ts → graph-B6NFqv3z.d.ts} +3 -3
- package/dist/{graph-ab1yPwIB.d.cts → graph-D-3JIQme.d.cts} +3 -3
- package/dist/{index-BvWfZCTt.d.cts → index-1z8vRTCt.d.cts} +3 -3
- package/dist/{index-Dy04P4W3.d.cts → index-AMWewNDe.d.cts} +2 -2
- package/dist/{index-C9z6rU9P.d.cts → index-BJB7t9gg.d.cts} +19 -15
- package/dist/{index-BbYZma8G.d.ts → index-BysCTzJz.d.ts} +3 -3
- package/dist/{index-HdJx_BjO.d.ts → index-C-TXEa7C.d.ts} +19 -15
- package/dist/{index-DsGxLfwL.d.ts → index-CYkjxu3s.d.ts} +2 -2
- package/dist/{index-BHm3Ba5q.d.ts → index-D7XgsUt7.d.ts} +2 -2
- package/dist/{index-D36MAQ3f.d.ts → index-DiobMNwE.d.ts} +3 -3
- package/dist/{index-DrJq9B1T.d.cts → index-J7Kc0oIQ.d.cts} +3 -3
- package/dist/{index-DLE1Sp-L.d.cts → index-b5BYtczN.d.cts} +2 -2
- package/dist/index.cjs +129 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +36 -42
- package/dist/index.js.map +1 -1
- package/dist/{meta-n3FoVWML.d.ts → meta-CnkLA_43.d.ts} +1 -1
- package/dist/{meta--fr9sxRM.d.cts → meta-DWbkoq1s.d.cts} +1 -1
- package/dist/{node-C5UD5MGq.d.cts → node-B-f-Lu-k.d.cts} +57 -13
- package/dist/{node-C5UD5MGq.d.ts → node-B-f-Lu-k.d.ts} +57 -13
- package/dist/{observable-DWydVy5b.d.cts → observable-DBnrwcar.d.cts} +1 -1
- package/dist/{observable-CQRBtEbq.d.ts → observable-uP-wy_uK.d.ts} +1 -1
- package/dist/patterns/reactive-layout/index.cjs +224 -129
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +5 -5
- package/dist/patterns/reactive-layout/index.d.ts +5 -5
- package/dist/patterns/reactive-layout/index.js +6 -4
- package/dist/{storage-Bew05Xy6.d.cts → storage-BuTdpCI1.d.cts} +1 -1
- package/dist/{storage-C9fZfMfM.d.ts → storage-F2X1U1x0.d.ts} +1 -1
- package/package.json +3 -2
- package/dist/chunk-EQUZ5NLD.js.map +0 -1
- package/dist/chunk-IR3KMOLX.js.map +0 -1
- package/dist/chunk-MQBQOFDS.js.map +0 -1
- package/dist/chunk-QA3RP5NH.js.map +0 -1
- /package/dist/{chunk-TH6COGOP.js.map → chunk-H4RVA4VE.js.map} +0 -0
- /package/dist/{chunk-44HD4BTA.js.map → chunk-MW4VAKAO.js.map} +0 -0
- /package/dist/{chunk-RHI3GHZW.js.map → chunk-QOWVNWOC.js.map} +0 -0
- /package/dist/{chunk-NXC35KC5.js.map → chunk-XOFWRC73.js.map} +0 -0
|
@@ -240,9 +240,20 @@ var flushInProgress = false;
|
|
|
240
240
|
var drainPhase2 = [];
|
|
241
241
|
var drainPhase3 = [];
|
|
242
242
|
var drainPhase4 = [];
|
|
243
|
+
var flushHooks = [];
|
|
243
244
|
function isBatching() {
|
|
244
245
|
return batchDepth > 0 || flushInProgress;
|
|
245
246
|
}
|
|
247
|
+
function isExplicitlyBatching() {
|
|
248
|
+
return batchDepth > 0;
|
|
249
|
+
}
|
|
250
|
+
function registerBatchFlushHook(hook) {
|
|
251
|
+
if (batchDepth > 0) {
|
|
252
|
+
flushHooks.push(hook);
|
|
253
|
+
} else {
|
|
254
|
+
hook();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
246
257
|
function batch(fn) {
|
|
247
258
|
batchDepth += 1;
|
|
248
259
|
let threw = false;
|
|
@@ -256,6 +267,13 @@ function batch(fn) {
|
|
|
256
267
|
if (batchDepth === 0) {
|
|
257
268
|
if (threw) {
|
|
258
269
|
if (!flushInProgress) {
|
|
270
|
+
const hooks = flushHooks.splice(0);
|
|
271
|
+
for (const h of hooks) {
|
|
272
|
+
try {
|
|
273
|
+
h();
|
|
274
|
+
} catch {
|
|
275
|
+
}
|
|
276
|
+
}
|
|
259
277
|
drainPhase2.length = 0;
|
|
260
278
|
drainPhase3.length = 0;
|
|
261
279
|
drainPhase4.length = 0;
|
|
@@ -272,7 +290,18 @@ function drainPending() {
|
|
|
272
290
|
const errors = [];
|
|
273
291
|
let iterations = 0;
|
|
274
292
|
try {
|
|
275
|
-
while (drainPhase2.length > 0 || drainPhase3.length > 0 || drainPhase4.length > 0) {
|
|
293
|
+
while (drainPhase2.length > 0 || drainPhase3.length > 0 || drainPhase4.length > 0 || ownsFlush && flushHooks.length > 0) {
|
|
294
|
+
if (ownsFlush && flushHooks.length > 0) {
|
|
295
|
+
const hooks = flushHooks.splice(0);
|
|
296
|
+
for (const h of hooks) {
|
|
297
|
+
try {
|
|
298
|
+
h();
|
|
299
|
+
} catch (e) {
|
|
300
|
+
errors.push(e);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
276
305
|
iterations += 1;
|
|
277
306
|
if (iterations > MAX_DRAIN_ITERATIONS) {
|
|
278
307
|
drainPhase2.length = 0;
|
|
@@ -962,6 +991,22 @@ var NodeImpl = class _NodeImpl {
|
|
|
962
991
|
* treats `0` as "wave settled" — O(1) check for full dep settlement.
|
|
963
992
|
*/
|
|
964
993
|
_dirtyDepCount = 0;
|
|
994
|
+
// --- Per-batch emit accumulator (Bug 2: K+1 fan-in fix) ---
|
|
995
|
+
/**
|
|
996
|
+
* Inside an explicit `batch(() => ...)` scope, every `_emit` accumulates
|
|
997
|
+
* its already-framed messages here instead of dispatching synchronously.
|
|
998
|
+
* At batch end, `_flushBatchPending` runs (registered via
|
|
999
|
+
* `registerBatchFlushHook`) and delivers the whole accumulated batch as
|
|
1000
|
+
* one `downWithBatch` call — collapsing what would otherwise be K
|
|
1001
|
+
* separate sink invocations into one. This is the fix for the diamond
|
|
1002
|
+
* fan-in K+1 over-fire.
|
|
1003
|
+
*
|
|
1004
|
+
* `null` outside batch (or after flush). Only ever appended to within
|
|
1005
|
+
* a single explicit batch lifetime; reset to `null` on flush. State
|
|
1006
|
+
* updates (cache, version, status) still happen per-emit via
|
|
1007
|
+
* `_updateState` — only the downstream delivery is coalesced.
|
|
1008
|
+
*/
|
|
1009
|
+
_batchPendingMessages = null;
|
|
965
1010
|
// --- PAUSE/RESUME lock tracking (C0) ---
|
|
966
1011
|
/**
|
|
967
1012
|
* Set of active pause locks held against this node. Every `[PAUSE, lockId]`
|
|
@@ -1339,7 +1384,10 @@ var NodeImpl = class _NodeImpl {
|
|
|
1339
1384
|
dep.unsub = noopUnsub;
|
|
1340
1385
|
dep.unsub = dep.node.subscribe((msgs) => {
|
|
1341
1386
|
if (dep.unsub === null) return;
|
|
1387
|
+
const tierOf = this._config.tierOf;
|
|
1388
|
+
let sawSettlement = false;
|
|
1342
1389
|
for (const m of msgs) {
|
|
1390
|
+
if (tierOf(m[0]) >= 3) sawSettlement = true;
|
|
1343
1391
|
this._config.onMessage(
|
|
1344
1392
|
this,
|
|
1345
1393
|
m,
|
|
@@ -1347,6 +1395,7 @@ var NodeImpl = class _NodeImpl {
|
|
|
1347
1395
|
this._actions
|
|
1348
1396
|
);
|
|
1349
1397
|
}
|
|
1398
|
+
if (sawSettlement) this._maybeRunFnOnSettlement();
|
|
1350
1399
|
});
|
|
1351
1400
|
subscribedCount++;
|
|
1352
1401
|
}
|
|
@@ -1401,7 +1450,10 @@ var NodeImpl = class _NodeImpl {
|
|
|
1401
1450
|
try {
|
|
1402
1451
|
record.unsub = depNode.subscribe((msgs) => {
|
|
1403
1452
|
if (record.unsub === null) return;
|
|
1453
|
+
const tierOf = this._config.tierOf;
|
|
1454
|
+
let sawSettlement = false;
|
|
1404
1455
|
for (const m of msgs) {
|
|
1456
|
+
if (tierOf(m[0]) >= 3) sawSettlement = true;
|
|
1405
1457
|
this._config.onMessage(
|
|
1406
1458
|
this,
|
|
1407
1459
|
m,
|
|
@@ -1409,6 +1461,7 @@ var NodeImpl = class _NodeImpl {
|
|
|
1409
1461
|
this._actions
|
|
1410
1462
|
);
|
|
1411
1463
|
}
|
|
1464
|
+
if (sawSettlement) this._maybeRunFnOnSettlement();
|
|
1412
1465
|
});
|
|
1413
1466
|
} catch (err) {
|
|
1414
1467
|
record.unsub = null;
|
|
@@ -1530,7 +1583,6 @@ var NodeImpl = class _NodeImpl {
|
|
|
1530
1583
|
}
|
|
1531
1584
|
return;
|
|
1532
1585
|
}
|
|
1533
|
-
this._maybeRunFnOnSettlement();
|
|
1534
1586
|
}
|
|
1535
1587
|
// --- Centralized dep-state transitions (A3 settlement counters) ---
|
|
1536
1588
|
//
|
|
@@ -1776,37 +1828,35 @@ var NodeImpl = class _NodeImpl {
|
|
|
1776
1828
|
// --- Emit pipeline ---
|
|
1777
1829
|
/**
|
|
1778
1830
|
* @internal The unified dispatch waist — one call = one wave.
|
|
1831
|
+
* See `GRAPHREFLY-SPEC.md` §1.3.1 for protocol context — the stages
|
|
1832
|
+
* below are the implementation order.
|
|
1779
1833
|
*
|
|
1780
1834
|
* Pipeline stages, in order:
|
|
1781
1835
|
*
|
|
1782
|
-
* 1.
|
|
1783
|
-
* 2. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE
|
|
1836
|
+
* 1. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE
|
|
1784
1837
|
* still propagate so graph teardown and cache-clear still work.
|
|
1785
|
-
*
|
|
1838
|
+
* 2. Tier sort (stable) — the batch can be in any order when it
|
|
1786
1839
|
* arrives; the walker downstream (`downWithBatch`) assumes
|
|
1787
1840
|
* ascending tier monotone, and so does `_updateState`'s tier-3
|
|
1788
1841
|
* slice walk. This is the single source of truth for ordering.
|
|
1789
|
-
*
|
|
1842
|
+
* 3. Synthetic DIRTY prefix — if a tier-3 payload is present, no
|
|
1790
1843
|
* DIRTY is already in the batch, and the node isn't already in
|
|
1791
1844
|
* `"dirty"` status, prepend `[DIRTY]` after any tier-0 START
|
|
1792
1845
|
* entries. Guarantees spec §1.3.1 (DIRTY precedes DATA within
|
|
1793
1846
|
* the same batch) uniformly across every entry point.
|
|
1794
|
-
*
|
|
1847
|
+
* 4. PAUSE/RESUME lock bookkeeping (C0) — update `_pauseLocks`,
|
|
1795
1848
|
* derive `_paused`, filter unknown-lockId RESUME, replay
|
|
1796
1849
|
* bufferAll buffer on final lock release.
|
|
1797
|
-
*
|
|
1850
|
+
* 5. Meta TEARDOWN fan-out — notify meta children before
|
|
1798
1851
|
* `_updateState`'s TEARDOWN branch calls `_deactivate`. Hoisted
|
|
1799
1852
|
* out of the walk to keep `_updateState` re-entrance-free.
|
|
1800
|
-
*
|
|
1853
|
+
* 6. `_updateState` — walk the batch in tier order, advancing
|
|
1801
1854
|
* `_cached` / `_status` / `_versioning` and running equals
|
|
1802
1855
|
* substitution on tier-3 DATA (§3.5.1). Returns
|
|
1803
1856
|
* `{finalMessages, equalsError?}`.
|
|
1804
|
-
*
|
|
1857
|
+
* 7. `downWithBatch` dispatch (or bufferAll capture if paused with
|
|
1805
1858
|
* `pausable: "resumeAll"`).
|
|
1806
|
-
*
|
|
1807
|
-
*
|
|
1808
|
-
* `node.down` / `node.emit` / `actions.down` / `actions.emit` all
|
|
1809
|
-
* converge here — the unified `_emit` waist (spec §1.3.1).
|
|
1859
|
+
* 8. Recursive ERROR emission if equals threw mid-walk.
|
|
1810
1860
|
*/
|
|
1811
1861
|
_emit(messages) {
|
|
1812
1862
|
if (messages.length === 0) return;
|
|
@@ -1902,10 +1952,10 @@ var NodeImpl = class _NodeImpl {
|
|
|
1902
1952
|
}
|
|
1903
1953
|
}
|
|
1904
1954
|
if (immediate.length > 0) {
|
|
1905
|
-
|
|
1955
|
+
this._dispatchOrAccumulate(immediate);
|
|
1906
1956
|
}
|
|
1907
1957
|
} else {
|
|
1908
|
-
|
|
1958
|
+
this._dispatchOrAccumulate(finalMessages);
|
|
1909
1959
|
}
|
|
1910
1960
|
}
|
|
1911
1961
|
if (equalsError != null) {
|
|
@@ -2028,6 +2078,50 @@ var NodeImpl = class _NodeImpl {
|
|
|
2028
2078
|
const snapshot = [...this._sinks];
|
|
2029
2079
|
for (const sink of snapshot) sink(messages);
|
|
2030
2080
|
};
|
|
2081
|
+
/**
|
|
2082
|
+
* @internal Dispatch entry point that respects the per-batch emit
|
|
2083
|
+
* accumulator (Bug 2). Inside an explicit `batch()` scope, append to
|
|
2084
|
+
* `_batchPendingMessages` and register a flush hook on first append.
|
|
2085
|
+
* Outside batch — or during a drain (where `flushInProgress` is true
|
|
2086
|
+
* but `batchDepth` is 0) — dispatch synchronously through `downWithBatch`.
|
|
2087
|
+
*
|
|
2088
|
+
* Per-emit state updates (`_frameBatch`, `_updateState`) have already
|
|
2089
|
+
* happened by the time we reach here; only the **downstream delivery**
|
|
2090
|
+
* is coalesced. Cache, version, and status are visible mid-batch on
|
|
2091
|
+
* the emitting node itself.
|
|
2092
|
+
*/
|
|
2093
|
+
_dispatchOrAccumulate(messages) {
|
|
2094
|
+
if (isExplicitlyBatching()) {
|
|
2095
|
+
if (this._batchPendingMessages === null) {
|
|
2096
|
+
this._batchPendingMessages = [];
|
|
2097
|
+
registerBatchFlushHook(() => this._flushBatchPending());
|
|
2098
|
+
}
|
|
2099
|
+
for (const m of messages) this._batchPendingMessages.push(m);
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
downWithBatch(this._deliverToSinks, messages, this._config.tierOf);
|
|
2103
|
+
}
|
|
2104
|
+
/**
|
|
2105
|
+
* @internal Flushes the accumulated batch through `downWithBatch` and
|
|
2106
|
+
* clears the pending state. Idempotent — safe to call when pending is
|
|
2107
|
+
* already null or empty (e.g. on a `batch()` throw, where the hook
|
|
2108
|
+
* fires for cleanup but the drainPhase queues are wiped after).
|
|
2109
|
+
*
|
|
2110
|
+
* Critical: the accumulated batch is interleaved per-emit framings like
|
|
2111
|
+
* `[DIRTY, DATA(1), DIRTY, DATA(2)]` — non-monotone tier order. We must
|
|
2112
|
+
* re-frame to sort by tier before handing to `downWithBatch`, which
|
|
2113
|
+
* assumes pre-sorted input. `_frameBatch` also handles the synthetic
|
|
2114
|
+
* DIRTY prepend rule (no-op here — `hasDirty` is true since each
|
|
2115
|
+
* accumulated emit already carries its own DIRTY prefix).
|
|
2116
|
+
*/
|
|
2117
|
+
_flushBatchPending() {
|
|
2118
|
+
const pending = this._batchPendingMessages;
|
|
2119
|
+
if (pending === null) return;
|
|
2120
|
+
this._batchPendingMessages = null;
|
|
2121
|
+
if (pending.length === 0) return;
|
|
2122
|
+
const framed = this._frameBatch(pending);
|
|
2123
|
+
downWithBatch(this._deliverToSinks, framed, this._config.tierOf);
|
|
2124
|
+
}
|
|
2031
2125
|
};
|
|
2032
2126
|
var isNodeArray = (value) => Array.isArray(value);
|
|
2033
2127
|
var isNodeOptionsObject = (value) => typeof value === "object" && value != null && !Array.isArray(value);
|
|
@@ -2231,4 +2325,4 @@ export {
|
|
|
2231
2325
|
autoTrackNode,
|
|
2232
2326
|
pipe
|
|
2233
2327
|
};
|
|
2234
|
-
//# sourceMappingURL=chunk-
|
|
2328
|
+
//# sourceMappingURL=chunk-5DJTTKX3.js.map
|