@graphrefly/graphrefly 0.25.0 → 0.26.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 +8 -0
- package/dist/{chunk-QOWVNWOC.js → chunk-3ZWCKRHX.js} +27 -25
- package/dist/{chunk-QOWVNWOC.js.map → chunk-3ZWCKRHX.js.map} +1 -1
- package/dist/chunk-6LDQFTYS.js +102 -0
- package/dist/chunk-6LDQFTYS.js.map +1 -0
- package/dist/{chunk-IAHGTNOZ.js → chunk-AMCG74RZ.js} +193 -24
- package/dist/chunk-AMCG74RZ.js.map +1 -0
- package/dist/{chunk-L2GLW2U7.js → chunk-BVZYTZ5H.js} +9 -103
- package/dist/chunk-BVZYTZ5H.js.map +1 -0
- package/dist/chunk-FQMKGR6L.js +330 -0
- package/dist/chunk-FQMKGR6L.js.map +1 -0
- package/dist/chunk-HXZEYDUR.js +94 -0
- package/dist/chunk-HXZEYDUR.js.map +1 -0
- package/dist/{chunk-EVR6UFUV.js → chunk-IZYUSJC7.js} +16 -14
- package/dist/{chunk-EVR6UFUV.js.map → chunk-IZYUSJC7.js.map} +1 -1
- package/dist/chunk-J22W6HV3.js +107 -0
- package/dist/chunk-J22W6HV3.js.map +1 -0
- package/dist/{chunk-HWPIFSW2.js → chunk-JSCT3CR4.js} +6 -4
- package/dist/{chunk-HWPIFSW2.js.map → chunk-JSCT3CR4.js.map} +1 -1
- package/dist/chunk-JYXEWPH4.js +62 -0
- package/dist/chunk-JYXEWPH4.js.map +1 -0
- package/dist/{chunk-TKE3JGOH.js → chunk-LCE3GF5P.js} +5 -692
- package/dist/chunk-LCE3GF5P.js.map +1 -0
- package/dist/chunk-MJ2NKQQL.js +119 -0
- package/dist/chunk-MJ2NKQQL.js.map +1 -0
- package/dist/chunk-N6UR7YVY.js +198 -0
- package/dist/chunk-N6UR7YVY.js.map +1 -0
- package/dist/chunk-OHISZPOJ.js +97 -0
- package/dist/chunk-OHISZPOJ.js.map +1 -0
- package/dist/{chunk-5DJTTKX3.js → chunk-PHOUUNK7.js} +74 -111
- package/dist/chunk-PHOUUNK7.js.map +1 -0
- package/dist/{chunk-PY4XCDLR.js → chunk-RB6QPHJ7.js} +8 -6
- package/dist/{chunk-PY4XCDLR.js.map → chunk-RB6QPHJ7.js.map} +1 -1
- package/dist/chunk-SN4YWWYO.js +171 -0
- package/dist/chunk-SN4YWWYO.js.map +1 -0
- package/dist/chunk-SX52TAR4.js +110 -0
- package/dist/chunk-SX52TAR4.js.map +1 -0
- package/dist/{chunk-XOFWRC73.js → chunk-THTWHNU4.js} +319 -24
- package/dist/chunk-THTWHNU4.js.map +1 -0
- package/dist/{chunk-H4RVA4VE.js → chunk-VYPWMZ6H.js} +2 -2
- package/dist/chunk-XGPU467M.js +136 -0
- package/dist/chunk-XGPU467M.js.map +1 -0
- package/dist/chunk-ZQMEI34O.js +713 -0
- package/dist/chunk-ZQMEI34O.js.map +1 -0
- package/dist/compat/index.cjs +7656 -0
- package/dist/compat/index.cjs.map +1 -0
- package/dist/compat/index.d.cts +18 -0
- package/dist/compat/index.d.ts +18 -0
- package/dist/compat/index.js +49 -0
- package/dist/compat/index.js.map +1 -0
- package/dist/compat/jotai/index.cjs +2048 -0
- package/dist/compat/jotai/index.cjs.map +1 -0
- package/dist/compat/jotai/index.d.cts +2 -0
- package/dist/compat/jotai/index.d.ts +2 -0
- package/dist/compat/jotai/index.js +9 -0
- package/dist/compat/jotai/index.js.map +1 -0
- package/dist/compat/nanostores/index.cjs +2175 -0
- package/dist/compat/nanostores/index.cjs.map +1 -0
- package/dist/compat/nanostores/index.d.cts +2 -0
- package/dist/compat/nanostores/index.d.ts +2 -0
- package/dist/compat/nanostores/index.js +23 -0
- package/dist/compat/nanostores/index.js.map +1 -0
- package/dist/compat/nestjs/index.cjs +350 -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 +10 -9
- package/dist/compat/react/index.cjs +141 -0
- package/dist/compat/react/index.cjs.map +1 -0
- package/dist/compat/react/index.d.cts +2 -0
- package/dist/compat/react/index.d.ts +2 -0
- package/dist/compat/react/index.js +12 -0
- package/dist/compat/react/index.js.map +1 -0
- package/dist/compat/solid/index.cjs +128 -0
- package/dist/compat/solid/index.cjs.map +1 -0
- package/dist/compat/solid/index.d.cts +2 -0
- package/dist/compat/solid/index.d.ts +2 -0
- package/dist/compat/solid/index.js +12 -0
- package/dist/compat/solid/index.js.map +1 -0
- package/dist/compat/svelte/index.cjs +131 -0
- package/dist/compat/svelte/index.cjs.map +1 -0
- package/dist/compat/svelte/index.d.cts +2 -0
- package/dist/compat/svelte/index.d.ts +2 -0
- package/dist/compat/svelte/index.js +12 -0
- package/dist/compat/svelte/index.js.map +1 -0
- package/dist/compat/vue/index.cjs +146 -0
- package/dist/compat/vue/index.cjs.map +1 -0
- package/dist/compat/vue/index.d.cts +3 -0
- package/dist/compat/vue/index.d.ts +3 -0
- package/dist/compat/vue/index.js +12 -0
- package/dist/compat/vue/index.js.map +1 -0
- package/dist/compat/zustand/index.cjs +4931 -0
- package/dist/compat/zustand/index.cjs.map +1 -0
- package/dist/compat/zustand/index.d.cts +5 -0
- package/dist/compat/zustand/index.d.ts +5 -0
- package/dist/compat/zustand/index.js +12 -0
- package/dist/compat/zustand/index.js.map +1 -0
- package/dist/core/index.cjs +53 -4
- 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 +26 -24
- package/dist/demo-shell-26p5fVxn.d.cts +102 -0
- package/dist/demo-shell-DEp-nMTl.d.ts +102 -0
- package/dist/extra/index.cjs +222 -110
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +5 -4
- package/dist/extra/index.d.ts +5 -4
- package/dist/extra/index.js +6 -5
- package/dist/extra/sources.cjs +2486 -0
- package/dist/extra/sources.cjs.map +1 -0
- package/dist/extra/sources.d.cts +465 -0
- package/dist/extra/sources.d.ts +465 -0
- package/dist/extra/sources.js +57 -0
- package/dist/extra/sources.js.map +1 -0
- package/dist/graph/index.cjs +408 -14
- 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 +13 -5
- package/dist/{graph-B6NFqv3z.d.ts → graph-6tZ5jEzr.d.cts} +195 -4
- package/dist/{graph-D-3JIQme.d.cts → graph-DQ69XU0g.d.ts} +195 -4
- package/dist/index-B4MP_8V_.d.cts +37 -0
- package/dist/index-BEfE8H_G.d.cts +121 -0
- package/dist/{index-OXImXMq6.d.ts → index-BW1z3BN9.d.ts} +18 -196
- package/dist/index-BYOHF0zP.d.ts +34 -0
- package/dist/index-B_IP40nB.d.cts +36 -0
- package/dist/index-Bd_fwmLf.d.cts +45 -0
- package/dist/{index-Ds23Wvou.d.ts → index-BeIdBfcb.d.cts} +120 -573
- package/dist/index-BjI6ty9z.d.ts +121 -0
- package/dist/index-Bxb5ZYc9.d.cts +34 -0
- package/dist/{index-BJB7t9gg.d.cts → index-C0ZXMaXO.d.cts} +2 -2
- package/dist/{index-DKE1EATr.d.cts → index-C8mdwMXc.d.cts} +18 -196
- package/dist/index-CDAjUFIv.d.ts +36 -0
- package/dist/index-CPgZ5wRl.d.ts +44 -0
- package/dist/{index-AMWewNDe.d.cts → index-CUwyr1Kk.d.cts} +33 -4
- package/dist/index-CUyrtuOf.d.cts +127 -0
- package/dist/{index-C-TXEa7C.d.ts → index-CY2TljO4.d.ts} +2 -2
- package/dist/index-CmnuOibw.d.ts +37 -0
- package/dist/{index-DiobMNwE.d.ts → index-CuYwdKO-.d.ts} +3 -3
- package/dist/index-DFhjO4Gg.d.cts +44 -0
- package/dist/{index-Ch0IpIO0.d.cts → index-DdD5MVDL.d.ts} +120 -573
- package/dist/index-DrISNAOm.d.ts +45 -0
- package/dist/index-QBpffFW-.d.cts +86 -0
- package/dist/{index-J7Kc0oIQ.d.cts → index-_oMEWlDq.d.cts} +3 -3
- package/dist/{index-CYkjxu3s.d.ts → index-eJ6T_qGM.d.ts} +33 -4
- package/dist/index-qldRdbQw.d.ts +86 -0
- package/dist/index-xdGjv0nO.d.ts +127 -0
- package/dist/index.cjs +1780 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1007 -648
- package/dist/index.d.ts +1007 -648
- package/dist/index.js +1202 -1172
- package/dist/index.js.map +1 -1
- package/dist/{meta-CnkLA_43.d.ts → meta-BGqSZ7mt.d.ts} +1 -1
- package/dist/{meta-DWbkoq1s.d.cts → meta-C0-8XW6Q.d.cts} +1 -1
- package/dist/{node-B-f-Lu-k.d.cts → node-C_IBuvX2.d.cts} +26 -1
- package/dist/{node-B-f-Lu-k.d.ts → node-C_IBuvX2.d.ts} +26 -1
- package/dist/{observable-DBnrwcar.d.cts → observable-Crr1jgzx.d.cts} +1 -1
- package/dist/{observable-uP-wy_uK.d.ts → observable-DCk45RH5.d.ts} +1 -1
- package/dist/patterns/demo-shell.cjs +5604 -0
- package/dist/patterns/demo-shell.cjs.map +1 -0
- package/dist/patterns/demo-shell.d.cts +6 -0
- package/dist/patterns/demo-shell.d.ts +6 -0
- package/dist/patterns/demo-shell.js +15 -0
- package/dist/patterns/demo-shell.js.map +1 -0
- package/dist/patterns/reactive-layout/index.cjs +355 -13
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +6 -5
- package/dist/patterns/reactive-layout/index.d.ts +6 -5
- package/dist/patterns/reactive-layout/index.js +15 -12
- package/dist/reactive-layout-BaOQefHu.d.cts +183 -0
- package/dist/reactive-layout-D9gejYXE.d.ts +183 -0
- package/dist/{storage-BuTdpCI1.d.cts → storage-BMycWEh2.d.ts} +9 -1
- package/dist/{storage-F2X1U1x0.d.ts → storage-DiqWHzVI.d.cts} +9 -1
- package/package.json +32 -2
- package/dist/chunk-5DJTTKX3.js.map +0 -1
- package/dist/chunk-IAHGTNOZ.js.map +0 -1
- package/dist/chunk-L2GLW2U7.js.map +0 -1
- package/dist/chunk-MW4VAKAO.js +0 -47
- package/dist/chunk-MW4VAKAO.js.map +0 -1
- package/dist/chunk-TKE3JGOH.js.map +0 -1
- package/dist/chunk-XOFWRC73.js.map +0 -1
- /package/dist/{chunk-H4RVA4VE.js.map → chunk-VYPWMZ6H.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
reactive_layout_exports
|
|
3
|
+
} from "./chunk-ZQMEI34O.js";
|
|
4
|
+
import {
|
|
5
|
+
compat_exports,
|
|
6
|
+
signals_exports
|
|
7
|
+
} from "./chunk-SN4YWWYO.js";
|
|
8
|
+
import {
|
|
9
|
+
nanostores_exports
|
|
10
|
+
} from "./chunk-N6UR7YVY.js";
|
|
11
|
+
import {
|
|
12
|
+
cqrs_exports,
|
|
13
|
+
nestjs_exports
|
|
14
|
+
} from "./chunk-IZYUSJC7.js";
|
|
15
|
+
import {
|
|
16
|
+
react_exports
|
|
17
|
+
} from "./chunk-J22W6HV3.js";
|
|
18
|
+
import {
|
|
19
|
+
solid_exports
|
|
20
|
+
} from "./chunk-HXZEYDUR.js";
|
|
21
|
+
import {
|
|
22
|
+
svelte_exports
|
|
23
|
+
} from "./chunk-OHISZPOJ.js";
|
|
24
|
+
import {
|
|
25
|
+
vue_exports
|
|
26
|
+
} from "./chunk-MJ2NKQQL.js";
|
|
27
|
+
import {
|
|
28
|
+
zustand_exports
|
|
29
|
+
} from "./chunk-JYXEWPH4.js";
|
|
1
30
|
import {
|
|
2
31
|
CircuitOpenError,
|
|
3
32
|
NS_PER_MS,
|
|
@@ -48,6 +77,7 @@ import {
|
|
|
48
77
|
fromCSV,
|
|
49
78
|
fromClickHouseWatch,
|
|
50
79
|
fromDrizzle,
|
|
80
|
+
fromFSWatch,
|
|
51
81
|
fromGitHook,
|
|
52
82
|
fromHTTP,
|
|
53
83
|
fromHTTPPoll,
|
|
@@ -148,33 +178,29 @@ import {
|
|
|
148
178
|
workerBridge,
|
|
149
179
|
workerSelf,
|
|
150
180
|
zip
|
|
151
|
-
} from "./chunk-
|
|
152
|
-
import {
|
|
153
|
-
cqrs_exports,
|
|
154
|
-
nestjs_exports
|
|
155
|
-
} from "./chunk-EVR6UFUV.js";
|
|
156
|
-
import {
|
|
157
|
-
core_exports
|
|
158
|
-
} from "./chunk-QOWVNWOC.js";
|
|
181
|
+
} from "./chunk-AMCG74RZ.js";
|
|
159
182
|
import {
|
|
160
183
|
NativeLogBackend,
|
|
161
184
|
createWatermarkController,
|
|
162
185
|
reactiveLog,
|
|
163
186
|
toObservable
|
|
164
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-RB6QPHJ7.js";
|
|
188
|
+
import {
|
|
189
|
+
core_exports
|
|
190
|
+
} from "./chunk-3ZWCKRHX.js";
|
|
165
191
|
import {
|
|
166
|
-
graph_exports
|
|
167
|
-
|
|
192
|
+
graph_exports,
|
|
193
|
+
watchTopologyTree
|
|
194
|
+
} from "./chunk-6LDQFTYS.js";
|
|
168
195
|
import {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
} from "./chunk-TKE3JGOH.js";
|
|
196
|
+
demo_shell_exports
|
|
197
|
+
} from "./chunk-FQMKGR6L.js";
|
|
198
|
+
import "./chunk-LCE3GF5P.js";
|
|
173
199
|
import {
|
|
174
200
|
domainMeta,
|
|
175
201
|
trackingKey,
|
|
176
202
|
tryIncrementBounded
|
|
177
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-JSCT3CR4.js";
|
|
178
204
|
import {
|
|
179
205
|
cached,
|
|
180
206
|
empty,
|
|
@@ -186,7 +212,6 @@ import {
|
|
|
186
212
|
fromAsyncIter,
|
|
187
213
|
fromCron,
|
|
188
214
|
fromEvent,
|
|
189
|
-
fromFSWatch,
|
|
190
215
|
fromIter,
|
|
191
216
|
fromPromise,
|
|
192
217
|
fromRaf,
|
|
@@ -204,53 +229,35 @@ import {
|
|
|
204
229
|
shareReplay,
|
|
205
230
|
throwError,
|
|
206
231
|
toArray
|
|
207
|
-
} from "./chunk-
|
|
232
|
+
} from "./chunk-BVZYTZ5H.js";
|
|
208
233
|
import {
|
|
209
234
|
GRAPH_META_SEGMENT,
|
|
210
235
|
Graph,
|
|
211
236
|
OVERHEAD,
|
|
212
237
|
SIZEOF_SYMBOL,
|
|
238
|
+
SNAPSHOT_VERSION,
|
|
213
239
|
diffForWAL,
|
|
240
|
+
explainPath,
|
|
214
241
|
graphProfile,
|
|
215
242
|
reachable,
|
|
216
243
|
sizeof
|
|
217
|
-
} from "./chunk-
|
|
218
|
-
import {
|
|
219
|
-
describeNode,
|
|
220
|
-
resolveDescribeFields
|
|
221
|
-
} from "./chunk-H4RVA4VE.js";
|
|
244
|
+
} from "./chunk-THTWHNU4.js";
|
|
222
245
|
import {
|
|
223
246
|
ResettableTimer
|
|
224
247
|
} from "./chunk-7TAQJHQV.js";
|
|
225
248
|
import {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
249
|
+
resolveDescribeFields
|
|
250
|
+
} from "./chunk-VYPWMZ6H.js";
|
|
251
|
+
import {
|
|
252
|
+
jotai_exports
|
|
253
|
+
} from "./chunk-XGPU467M.js";
|
|
254
|
+
import {
|
|
230
255
|
DEFAULT_ACTOR,
|
|
231
|
-
DIRTY,
|
|
232
|
-
DIRTY_MSG,
|
|
233
|
-
DIRTY_ONLY_BATCH,
|
|
234
256
|
ENVELOPE_VERSION,
|
|
235
|
-
ERROR,
|
|
236
257
|
GraphReFlyConfig,
|
|
237
258
|
GuardDenied,
|
|
238
|
-
INVALIDATE,
|
|
239
|
-
INVALIDATE_MSG,
|
|
240
|
-
INVALIDATE_ONLY_BATCH,
|
|
241
259
|
JsonCodec,
|
|
242
260
|
NodeImpl,
|
|
243
|
-
PAUSE,
|
|
244
|
-
RESOLVED,
|
|
245
|
-
RESOLVED_MSG,
|
|
246
|
-
RESOLVED_ONLY_BATCH,
|
|
247
|
-
RESUME,
|
|
248
|
-
START,
|
|
249
|
-
START_MSG,
|
|
250
|
-
TEARDOWN,
|
|
251
|
-
TEARDOWN_MSG,
|
|
252
|
-
TEARDOWN_ONLY_BATCH,
|
|
253
|
-
__export,
|
|
254
261
|
accessHintForGuard,
|
|
255
262
|
advanceVersion,
|
|
256
263
|
autoTrackNode,
|
|
@@ -281,855 +288,61 @@ import {
|
|
|
281
288
|
replayWAL,
|
|
282
289
|
state,
|
|
283
290
|
wallClockNs
|
|
284
|
-
} from "./chunk-
|
|
285
|
-
|
|
286
|
-
// src/compat/index.ts
|
|
287
|
-
var compat_exports = {};
|
|
288
|
-
__export(compat_exports, {
|
|
289
|
-
jotai: () => jotai_exports,
|
|
290
|
-
nanostores: () => nanostores_exports,
|
|
291
|
-
nestjs: () => nestjs_exports,
|
|
292
|
-
react: () => react_exports,
|
|
293
|
-
signals: () => signals_exports,
|
|
294
|
-
solid: () => solid_exports,
|
|
295
|
-
svelte: () => svelte_exports,
|
|
296
|
-
vue: () => vue_exports,
|
|
297
|
-
zustand: () => zustand_exports
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// src/compat/jotai/index.ts
|
|
301
|
-
var jotai_exports = {};
|
|
302
|
-
__export(jotai_exports, {
|
|
303
|
-
atom: () => atom
|
|
304
|
-
});
|
|
305
|
-
function atom(initialOrRead, writeOrOptions, options) {
|
|
306
|
-
if (typeof initialOrRead === "function") {
|
|
307
|
-
const read = initialOrRead;
|
|
308
|
-
if (typeof writeOrOptions === "function") {
|
|
309
|
-
return createDerivedAtom(read, writeOrOptions, options);
|
|
310
|
-
}
|
|
311
|
-
return createDerivedAtom(read, void 0, writeOrOptions);
|
|
312
|
-
}
|
|
313
|
-
return createPrimitiveAtom(initialOrRead, writeOrOptions);
|
|
314
|
-
}
|
|
315
|
-
function pull(n) {
|
|
316
|
-
let val = n.cache;
|
|
317
|
-
let err;
|
|
318
|
-
const unsub = n.subscribe((msgs) => {
|
|
319
|
-
for (const [t, v] of msgs) {
|
|
320
|
-
if (t === DATA) val = v;
|
|
321
|
-
if (t === ERROR) err = v;
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
unsub();
|
|
325
|
-
if (err) throw err;
|
|
326
|
-
return val;
|
|
327
|
-
}
|
|
328
|
-
function createPrimitiveAtom(initial, options) {
|
|
329
|
-
const n = state(initial, {
|
|
330
|
-
...options,
|
|
331
|
-
resubscribable: true,
|
|
332
|
-
resetOnTeardown: true
|
|
333
|
-
});
|
|
334
|
-
return {
|
|
335
|
-
get: () => {
|
|
336
|
-
if (n.status === "sentinel") {
|
|
337
|
-
return pull(n);
|
|
338
|
-
}
|
|
339
|
-
return n.cache;
|
|
340
|
-
},
|
|
341
|
-
// Use `n.emit` (not raw `n.down`) so writes go through the framed
|
|
342
|
-
// emit pipeline: bundle() auto-prefixes DIRTY (diamond-safe wave
|
|
343
|
-
// coordination) and the equals check folds same-value writes to
|
|
344
|
-
// RESOLVED (no spurious subscriber fires).
|
|
345
|
-
set: (value) => n.emit(value),
|
|
346
|
-
update: (fn) => {
|
|
347
|
-
const current = n.status === "sentinel" ? pull(n) : n.cache;
|
|
348
|
-
n.emit(fn(current));
|
|
349
|
-
},
|
|
350
|
-
subscribe: (cb) => {
|
|
351
|
-
let initial2 = true;
|
|
352
|
-
return n.subscribe((msgs) => {
|
|
353
|
-
for (const [t, v] of msgs) {
|
|
354
|
-
if (t === DATA) {
|
|
355
|
-
if (initial2) {
|
|
356
|
-
initial2 = false;
|
|
357
|
-
continue;
|
|
358
|
-
}
|
|
359
|
-
cb(v);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
},
|
|
364
|
-
meta: n.meta,
|
|
365
|
-
_node: n
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
function createDerivedAtom(read, write, options) {
|
|
369
|
-
const n = autoTrackNode(
|
|
370
|
-
(track) => read((a) => {
|
|
371
|
-
const dn = a._node;
|
|
372
|
-
if (dn.status === "sentinel") {
|
|
373
|
-
pull(dn);
|
|
374
|
-
}
|
|
375
|
-
return track(dn);
|
|
376
|
-
}),
|
|
377
|
-
{
|
|
378
|
-
...options,
|
|
379
|
-
resubscribable: true,
|
|
380
|
-
resetOnTeardown: true
|
|
381
|
-
}
|
|
382
|
-
);
|
|
383
|
-
const result = {
|
|
384
|
-
get: () => {
|
|
385
|
-
if (n.status === "sentinel") {
|
|
386
|
-
return pull(n);
|
|
387
|
-
}
|
|
388
|
-
return n.cache;
|
|
389
|
-
},
|
|
390
|
-
subscribe: (cb) => {
|
|
391
|
-
let initial = true;
|
|
392
|
-
return n.subscribe((msgs) => {
|
|
393
|
-
for (const [t, v] of msgs) {
|
|
394
|
-
if (t === DATA) {
|
|
395
|
-
if (initial) {
|
|
396
|
-
initial = false;
|
|
397
|
-
continue;
|
|
398
|
-
}
|
|
399
|
-
cb(v);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
},
|
|
404
|
-
meta: n.meta,
|
|
405
|
-
_node: n
|
|
406
|
-
};
|
|
407
|
-
if (write) {
|
|
408
|
-
const getFn = (a) => a.get();
|
|
409
|
-
const setFn = (a, value) => a.set(value);
|
|
410
|
-
const writable = result;
|
|
411
|
-
writable.set = (value) => write(getFn, setFn, value);
|
|
412
|
-
writable.update = (fn) => {
|
|
413
|
-
const current = n.status === "sentinel" ? pull(n) : n.cache;
|
|
414
|
-
return write(getFn, setFn, fn(current));
|
|
415
|
-
};
|
|
416
|
-
return writable;
|
|
417
|
-
}
|
|
418
|
-
return result;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// src/compat/nanostores/index.ts
|
|
422
|
-
var nanostores_exports = {};
|
|
423
|
-
__export(nanostores_exports, {
|
|
424
|
-
action: () => action,
|
|
425
|
-
atom: () => atom2,
|
|
426
|
-
computed: () => computed,
|
|
427
|
-
getValue: () => getValue,
|
|
428
|
-
map: () => map2,
|
|
429
|
-
onMount: () => onMount,
|
|
430
|
-
onStart: () => onStart,
|
|
431
|
-
onStop: () => onStop
|
|
432
|
-
});
|
|
433
|
-
var START_LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
434
|
-
var STOP_LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
435
|
-
function trigger(node2, map3) {
|
|
436
|
-
const callbacks = map3.get(node2);
|
|
437
|
-
if (callbacks) {
|
|
438
|
-
for (const cb of callbacks) cb();
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
function createStore(node2, extra = {}) {
|
|
442
|
-
let listeners = 0;
|
|
443
|
-
const store = {
|
|
444
|
-
...extra,
|
|
445
|
-
get: () => getVal(node2),
|
|
446
|
-
subscribe: (cb) => {
|
|
447
|
-
if (listeners === 0) trigger(node2, START_LISTENERS);
|
|
448
|
-
listeners++;
|
|
449
|
-
const sub = node2.subscribe((msgs) => {
|
|
450
|
-
for (const [t, v] of msgs) {
|
|
451
|
-
if (t === DATA) cb(v);
|
|
452
|
-
}
|
|
453
|
-
});
|
|
454
|
-
return () => {
|
|
455
|
-
sub();
|
|
456
|
-
listeners--;
|
|
457
|
-
if (listeners === 0) trigger(node2, STOP_LISTENERS);
|
|
458
|
-
};
|
|
459
|
-
},
|
|
460
|
-
listen: (cb) => {
|
|
461
|
-
if (listeners === 0) trigger(node2, START_LISTENERS);
|
|
462
|
-
listeners++;
|
|
463
|
-
let initial = true;
|
|
464
|
-
const sub = node2.subscribe((msgs) => {
|
|
465
|
-
for (const [t, v] of msgs) {
|
|
466
|
-
if (t === DATA) {
|
|
467
|
-
if (initial) {
|
|
468
|
-
initial = false;
|
|
469
|
-
continue;
|
|
470
|
-
}
|
|
471
|
-
cb(v);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
return () => {
|
|
476
|
-
sub();
|
|
477
|
-
listeners--;
|
|
478
|
-
if (listeners === 0) trigger(node2, STOP_LISTENERS);
|
|
479
|
-
};
|
|
480
|
-
},
|
|
481
|
-
_node: node2
|
|
482
|
-
};
|
|
483
|
-
return store;
|
|
484
|
-
}
|
|
485
|
-
function pull2(n) {
|
|
486
|
-
let val = n.cache;
|
|
487
|
-
let err;
|
|
488
|
-
const unsub = n.subscribe((msgs) => {
|
|
489
|
-
for (const [t, v] of msgs) {
|
|
490
|
-
if (t === DATA) val = v;
|
|
491
|
-
if (t === ERROR) err = v;
|
|
492
|
-
}
|
|
493
|
-
});
|
|
494
|
-
unsub();
|
|
495
|
-
if (err) throw err;
|
|
496
|
-
return val;
|
|
497
|
-
}
|
|
498
|
-
function getVal(n) {
|
|
499
|
-
if (n.status === "sentinel") {
|
|
500
|
-
return pull2(n);
|
|
501
|
-
}
|
|
502
|
-
return n.cache;
|
|
503
|
-
}
|
|
504
|
-
function atom2(initial) {
|
|
505
|
-
const n = state(initial, {
|
|
506
|
-
resubscribable: true,
|
|
507
|
-
resetOnTeardown: true
|
|
508
|
-
});
|
|
509
|
-
return createStore(n, {
|
|
510
|
-
// `n.emit` routes through the framed pipeline: `bundle()` auto-
|
|
511
|
-
// prefixes `[DIRTY]` (diamond-safe wave coordination) and the
|
|
512
|
-
// node's `equals` (default `Object.is`) folds same-value writes
|
|
513
|
-
// into `RESOLVED`. Matches nanostores' documented Object.is
|
|
514
|
-
// dedup semantics without any custom check.
|
|
515
|
-
set: (value) => n.emit(value)
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
function computed(stores, fn) {
|
|
519
|
-
const storeArray = Array.isArray(stores) ? stores : [stores];
|
|
520
|
-
const depNodes = storeArray.map((s) => s._node);
|
|
521
|
-
const n = dynamicNode(
|
|
522
|
-
depNodes,
|
|
523
|
-
(track) => {
|
|
524
|
-
const vals = storeArray.map((s) => {
|
|
525
|
-
const node2 = s._node;
|
|
526
|
-
if (node2.status === "sentinel") {
|
|
527
|
-
pull2(node2);
|
|
528
|
-
}
|
|
529
|
-
return track(node2);
|
|
530
|
-
});
|
|
531
|
-
return fn(...vals);
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
resubscribable: true,
|
|
535
|
-
resetOnTeardown: true,
|
|
536
|
-
equals: Object.is
|
|
537
|
-
}
|
|
538
|
-
);
|
|
539
|
-
return createStore(n);
|
|
540
|
-
}
|
|
541
|
-
function map2(initial) {
|
|
542
|
-
const n = state(initial, {
|
|
543
|
-
resubscribable: true,
|
|
544
|
-
resetOnTeardown: true,
|
|
545
|
-
equals: () => false
|
|
546
|
-
});
|
|
547
|
-
return createStore(n, {
|
|
548
|
-
// `map`'s state node is configured with `equals: () => false`
|
|
549
|
-
// above, so every `emit` produces DATA (even for same-key same-
|
|
550
|
-
// value sets). The `emit` path is still required for diamond
|
|
551
|
-
// coordination (`[DIRTY]` auto-prefix via `bundle()`).
|
|
552
|
-
set: (value) => n.emit(value),
|
|
553
|
-
setKey: (key, value) => {
|
|
554
|
-
const current = getVal(n);
|
|
555
|
-
n.emit({ ...current, [key]: value });
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
function getValue(store) {
|
|
560
|
-
return store.get();
|
|
561
|
-
}
|
|
562
|
-
function onStart(store, cb) {
|
|
563
|
-
const node2 = store._node;
|
|
564
|
-
let callbacks = START_LISTENERS.get(node2);
|
|
565
|
-
if (!callbacks) {
|
|
566
|
-
callbacks = /* @__PURE__ */ new Set();
|
|
567
|
-
START_LISTENERS.set(node2, callbacks);
|
|
568
|
-
}
|
|
569
|
-
callbacks.add(cb);
|
|
570
|
-
}
|
|
571
|
-
function onStop(store, cb) {
|
|
572
|
-
const node2 = store._node;
|
|
573
|
-
let callbacks = STOP_LISTENERS.get(node2);
|
|
574
|
-
if (!callbacks) {
|
|
575
|
-
callbacks = /* @__PURE__ */ new Set();
|
|
576
|
-
STOP_LISTENERS.set(node2, callbacks);
|
|
577
|
-
}
|
|
578
|
-
callbacks.add(cb);
|
|
579
|
-
}
|
|
580
|
-
function onMount(store, cb) {
|
|
581
|
-
onStart(store, () => {
|
|
582
|
-
const stop = cb();
|
|
583
|
-
if (typeof stop === "function") onStop(store, stop);
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
function action(_store, _name, fn) {
|
|
587
|
-
return (...args) => {
|
|
588
|
-
let result;
|
|
589
|
-
batch(() => {
|
|
590
|
-
result = fn(...args);
|
|
591
|
-
});
|
|
592
|
-
return result;
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// src/compat/react/index.ts
|
|
597
|
-
var react_exports = {};
|
|
598
|
-
__export(react_exports, {
|
|
599
|
-
useStore: () => useStore,
|
|
600
|
-
useSubscribe: () => useSubscribe,
|
|
601
|
-
useSubscribeRecord: () => useSubscribeRecord
|
|
602
|
-
});
|
|
603
|
-
import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
|
|
604
|
-
function useSubscribe(node2) {
|
|
605
|
-
return useSyncExternalStore(
|
|
606
|
-
(onStoreChange) => {
|
|
607
|
-
let disposed = false;
|
|
608
|
-
const unsub = node2.subscribe(() => {
|
|
609
|
-
if (!disposed) onStoreChange();
|
|
610
|
-
});
|
|
611
|
-
return () => {
|
|
612
|
-
disposed = true;
|
|
613
|
-
unsub();
|
|
614
|
-
};
|
|
615
|
-
},
|
|
616
|
-
() => node2.cache,
|
|
617
|
-
() => node2.cache
|
|
618
|
-
// Server snapshot
|
|
619
|
-
);
|
|
620
|
-
}
|
|
621
|
-
function useStore(node2) {
|
|
622
|
-
const value = useSubscribe(node2);
|
|
623
|
-
const setter = useCallback(
|
|
624
|
-
(v) => {
|
|
625
|
-
node2.down([[DIRTY], [DATA, v]]);
|
|
626
|
-
},
|
|
627
|
-
[node2]
|
|
628
|
-
);
|
|
629
|
-
return [value, setter];
|
|
630
|
-
}
|
|
631
|
-
function useSubscribeRecord(keysNode, factory) {
|
|
632
|
-
const factoryRef = useRef(factory);
|
|
633
|
-
factoryRef.current = factory;
|
|
634
|
-
const store = useMemo(() => {
|
|
635
|
-
const computeSnap = () => {
|
|
636
|
-
const snap = {};
|
|
637
|
-
const keys = keysNode.cache ?? [];
|
|
638
|
-
for (const key of keys) {
|
|
639
|
-
const nodes = factoryRef.current(key);
|
|
640
|
-
const values = {};
|
|
641
|
-
for (const field of Object.keys(nodes)) {
|
|
642
|
-
values[field] = nodes[field].cache;
|
|
643
|
-
}
|
|
644
|
-
snap[key] = values;
|
|
645
|
-
}
|
|
646
|
-
return snap;
|
|
647
|
-
};
|
|
648
|
-
let currentSnapshot = computeSnap();
|
|
649
|
-
return {
|
|
650
|
-
subscribe: (onStoreChange) => {
|
|
651
|
-
let disposed = false;
|
|
652
|
-
let entrySubs = [];
|
|
653
|
-
const cleanupEntries = () => {
|
|
654
|
-
for (const unsub of entrySubs) unsub();
|
|
655
|
-
entrySubs = [];
|
|
656
|
-
};
|
|
657
|
-
const sync = (nextKeys) => {
|
|
658
|
-
cleanupEntries();
|
|
659
|
-
for (const key of nextKeys) {
|
|
660
|
-
const nodes = factoryRef.current(key);
|
|
661
|
-
for (const field of Object.keys(nodes)) {
|
|
662
|
-
const unsub = nodes[field].subscribe(() => {
|
|
663
|
-
currentSnapshot = computeSnap();
|
|
664
|
-
if (!disposed) onStoreChange();
|
|
665
|
-
});
|
|
666
|
-
entrySubs.push(unsub);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
currentSnapshot = computeSnap();
|
|
670
|
-
if (!disposed) onStoreChange();
|
|
671
|
-
};
|
|
672
|
-
const keysUnsub = keysNode.subscribe((msgs) => {
|
|
673
|
-
const hasSettled = msgs.some((m) => m[0] === DATA || m[0] === RESOLVED);
|
|
674
|
-
if (!disposed && hasSettled) sync(keysNode.cache ?? []);
|
|
675
|
-
});
|
|
676
|
-
sync(keysNode.cache ?? []);
|
|
677
|
-
return () => {
|
|
678
|
-
disposed = true;
|
|
679
|
-
keysUnsub();
|
|
680
|
-
cleanupEntries();
|
|
681
|
-
};
|
|
682
|
-
},
|
|
683
|
-
getSnapshot: () => currentSnapshot
|
|
684
|
-
};
|
|
685
|
-
}, [keysNode]);
|
|
686
|
-
return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// src/compat/signals/index.ts
|
|
690
|
-
var signals_exports = {};
|
|
691
|
-
__export(signals_exports, {
|
|
692
|
-
Signal: () => Signal
|
|
693
|
-
});
|
|
694
|
-
var trackingStack = [];
|
|
695
|
-
function pull3(n) {
|
|
696
|
-
let val = n.cache;
|
|
697
|
-
const unsub = n.subscribe((msgs) => {
|
|
698
|
-
for (const [t, v] of msgs) {
|
|
699
|
-
if (t === DATA) val = v;
|
|
700
|
-
}
|
|
701
|
-
});
|
|
702
|
-
unsub();
|
|
703
|
-
return val;
|
|
704
|
-
}
|
|
705
|
-
var SignalState = class {
|
|
706
|
-
/** @internal */
|
|
707
|
-
_node;
|
|
708
|
-
_equals;
|
|
709
|
-
constructor(initial, opts) {
|
|
710
|
-
this._equals = opts?.equals ?? Object.is;
|
|
711
|
-
this._node = state(initial, {
|
|
712
|
-
...opts,
|
|
713
|
-
resubscribable: true,
|
|
714
|
-
resetOnTeardown: true
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
get() {
|
|
718
|
-
const tracker = trackingStack[trackingStack.length - 1];
|
|
719
|
-
if (tracker) {
|
|
720
|
-
if (this._node.status === "sentinel") {
|
|
721
|
-
pull3(this._node);
|
|
722
|
-
}
|
|
723
|
-
return tracker(this._node);
|
|
724
|
-
}
|
|
725
|
-
if (this._node.status === "sentinel") {
|
|
726
|
-
return pull3(this._node);
|
|
727
|
-
}
|
|
728
|
-
return this._node.cache;
|
|
729
|
-
}
|
|
730
|
-
set(value) {
|
|
731
|
-
if (this._equals(this.get(), value)) return;
|
|
732
|
-
batch(() => {
|
|
733
|
-
this._node.down([[DIRTY], [DATA, value]]);
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
var SignalComputed = class {
|
|
738
|
-
/** @internal */
|
|
739
|
-
_node;
|
|
740
|
-
constructor(computation, opts) {
|
|
741
|
-
this._node = autoTrackNode(
|
|
742
|
-
(track) => {
|
|
743
|
-
trackingStack.push(track);
|
|
744
|
-
try {
|
|
745
|
-
return computation();
|
|
746
|
-
} finally {
|
|
747
|
-
trackingStack.pop();
|
|
748
|
-
}
|
|
749
|
-
},
|
|
750
|
-
{
|
|
751
|
-
...opts,
|
|
752
|
-
describeKind: "derived",
|
|
753
|
-
resubscribable: true,
|
|
754
|
-
resetOnTeardown: true
|
|
755
|
-
}
|
|
756
|
-
);
|
|
757
|
-
}
|
|
758
|
-
get() {
|
|
759
|
-
const tracker = trackingStack[trackingStack.length - 1];
|
|
760
|
-
if (tracker) {
|
|
761
|
-
if (this._node.status === "sentinel") {
|
|
762
|
-
pull3(this._node);
|
|
763
|
-
}
|
|
764
|
-
return tracker(this._node);
|
|
765
|
-
}
|
|
766
|
-
if (this._node.status === "sentinel") {
|
|
767
|
-
return pull3(this._node);
|
|
768
|
-
}
|
|
769
|
-
return this._node.cache;
|
|
770
|
-
}
|
|
771
|
-
};
|
|
772
|
-
var Signal = {
|
|
773
|
-
State: SignalState,
|
|
774
|
-
Computed: SignalComputed,
|
|
775
|
-
/**
|
|
776
|
-
* Subscribes to changes on a signal.
|
|
777
|
-
* Returns an unsubscribe callback.
|
|
778
|
-
*
|
|
779
|
-
* @example
|
|
780
|
-
* ```ts
|
|
781
|
-
* const count = new Signal.State(0);
|
|
782
|
-
* const unsub = Signal.sub(count, v => console.log(v));
|
|
783
|
-
* ```
|
|
784
|
-
*/
|
|
785
|
-
sub: (signal, callback) => {
|
|
786
|
-
const handlers = typeof callback === "function" ? { data: callback, error: void 0, complete: void 0 } : callback;
|
|
787
|
-
let initial = true;
|
|
788
|
-
return signal._node.subscribe((msgs) => {
|
|
789
|
-
for (const [t, v] of msgs) {
|
|
790
|
-
if (t === DATA) {
|
|
791
|
-
if (initial) {
|
|
792
|
-
initial = false;
|
|
793
|
-
continue;
|
|
794
|
-
}
|
|
795
|
-
handlers.data?.(v);
|
|
796
|
-
}
|
|
797
|
-
if (t === ERROR) handlers.error?.(v);
|
|
798
|
-
if (t === COMPLETE) handlers.complete?.();
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
};
|
|
803
|
-
|
|
804
|
-
// src/compat/solid/index.ts
|
|
805
|
-
var solid_exports = {};
|
|
806
|
-
__export(solid_exports, {
|
|
807
|
-
useStore: () => useStore2,
|
|
808
|
-
useSubscribe: () => useSubscribe2,
|
|
809
|
-
useSubscribeRecord: () => useSubscribeRecord2
|
|
810
|
-
});
|
|
811
|
-
import { createSignal, getOwner, onCleanup } from "solid-js";
|
|
812
|
-
function useSubscribe2(node2) {
|
|
813
|
-
const [value, setValue] = createSignal(node2.cache, { equals: false });
|
|
814
|
-
const unsub = node2.subscribe(() => {
|
|
815
|
-
setValue(() => node2.cache);
|
|
816
|
-
});
|
|
817
|
-
if (getOwner()) {
|
|
818
|
-
onCleanup(() => unsub());
|
|
819
|
-
} else if (typeof console !== "undefined") {
|
|
820
|
-
console.warn(
|
|
821
|
-
"[graphrefly-ts] useSubscribe called outside a Solid reactive owner \u2014 subscription will not be auto-disposed."
|
|
822
|
-
);
|
|
823
|
-
}
|
|
824
|
-
return value;
|
|
825
|
-
}
|
|
826
|
-
function useStore2(node2) {
|
|
827
|
-
const value = useSubscribe2(node2);
|
|
828
|
-
const setter = (v) => {
|
|
829
|
-
node2.down([[DIRTY], [DATA, v]]);
|
|
830
|
-
};
|
|
831
|
-
return [value, setter];
|
|
832
|
-
}
|
|
833
|
-
function useSubscribeRecord2(keysNode, factory) {
|
|
834
|
-
const [value, setValue] = createSignal({}, { equals: false });
|
|
835
|
-
let entrySubs = [];
|
|
836
|
-
const cleanupEntries = () => {
|
|
837
|
-
for (const unsub of entrySubs) unsub();
|
|
838
|
-
entrySubs = [];
|
|
839
|
-
};
|
|
840
|
-
const buildSnapshot = () => {
|
|
841
|
-
const snap = {};
|
|
842
|
-
for (const key of keysNode.cache ?? []) {
|
|
843
|
-
const nodes = factory(key);
|
|
844
|
-
const values = {};
|
|
845
|
-
for (const field of Object.keys(nodes)) {
|
|
846
|
-
values[field] = nodes[field].cache;
|
|
847
|
-
}
|
|
848
|
-
snap[key] = values;
|
|
849
|
-
}
|
|
850
|
-
return snap;
|
|
851
|
-
};
|
|
852
|
-
const sync = (nextKeys) => {
|
|
853
|
-
cleanupEntries();
|
|
854
|
-
for (const key of nextKeys) {
|
|
855
|
-
const nodes = factory(key);
|
|
856
|
-
for (const field of Object.keys(nodes)) {
|
|
857
|
-
const unsub = nodes[field].subscribe(() => {
|
|
858
|
-
setValue(() => buildSnapshot());
|
|
859
|
-
});
|
|
860
|
-
entrySubs.push(unsub);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
setValue(() => buildSnapshot());
|
|
864
|
-
};
|
|
865
|
-
const keysUnsub = keysNode.subscribe((msgs) => {
|
|
866
|
-
if (msgs.some((m) => m[0] === DATA || m[0] === RESOLVED)) {
|
|
867
|
-
sync(keysNode.cache ?? []);
|
|
868
|
-
}
|
|
869
|
-
});
|
|
870
|
-
sync(keysNode.cache ?? []);
|
|
871
|
-
if (getOwner()) {
|
|
872
|
-
onCleanup(() => {
|
|
873
|
-
keysUnsub();
|
|
874
|
-
cleanupEntries();
|
|
875
|
-
});
|
|
876
|
-
} else if (typeof console !== "undefined") {
|
|
877
|
-
console.warn(
|
|
878
|
-
"[graphrefly-ts] useSubscribeRecord called outside a Solid reactive owner \u2014 subscription will not be auto-disposed."
|
|
879
|
-
);
|
|
880
|
-
}
|
|
881
|
-
return value;
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
// src/compat/svelte/index.ts
|
|
885
|
-
var svelte_exports = {};
|
|
886
|
-
__export(svelte_exports, {
|
|
887
|
-
useStore: () => useStore3,
|
|
888
|
-
useSubscribe: () => useSubscribe3,
|
|
889
|
-
useSubscribeRecord: () => useSubscribeRecord3
|
|
890
|
-
});
|
|
891
|
-
function useSubscribe3(node2) {
|
|
892
|
-
return {
|
|
893
|
-
subscribe(run) {
|
|
894
|
-
const unsub = node2.subscribe(() => {
|
|
895
|
-
run(node2.cache);
|
|
896
|
-
});
|
|
897
|
-
run(node2.cache);
|
|
898
|
-
return unsub;
|
|
899
|
-
}
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
|
-
function useStore3(node2) {
|
|
903
|
-
return {
|
|
904
|
-
subscribe(run) {
|
|
905
|
-
const unsub = node2.subscribe(() => {
|
|
906
|
-
run(node2.cache);
|
|
907
|
-
});
|
|
908
|
-
run(node2.cache);
|
|
909
|
-
return unsub;
|
|
910
|
-
},
|
|
911
|
-
set(value) {
|
|
912
|
-
node2.down([[DIRTY], [DATA, value]]);
|
|
913
|
-
},
|
|
914
|
-
update(updater) {
|
|
915
|
-
const next = updater(node2.cache);
|
|
916
|
-
node2.down([[DIRTY], [DATA, next]]);
|
|
917
|
-
}
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
function useSubscribeRecord3(keysNode, factory) {
|
|
921
|
-
return {
|
|
922
|
-
subscribe(run) {
|
|
923
|
-
let entrySubs = [];
|
|
924
|
-
const cleanupEntries = () => {
|
|
925
|
-
for (const unsub of entrySubs) unsub();
|
|
926
|
-
entrySubs = [];
|
|
927
|
-
};
|
|
928
|
-
const buildSnapshot = () => {
|
|
929
|
-
const snap = {};
|
|
930
|
-
for (const key of keysNode.cache ?? []) {
|
|
931
|
-
const nodes = factory(key);
|
|
932
|
-
const values = {};
|
|
933
|
-
for (const field of Object.keys(nodes)) {
|
|
934
|
-
values[field] = nodes[field].cache;
|
|
935
|
-
}
|
|
936
|
-
snap[key] = values;
|
|
937
|
-
}
|
|
938
|
-
return snap;
|
|
939
|
-
};
|
|
940
|
-
const sync = (nextKeys) => {
|
|
941
|
-
cleanupEntries();
|
|
942
|
-
for (const key of nextKeys) {
|
|
943
|
-
const nodes = factory(key);
|
|
944
|
-
for (const field of Object.keys(nodes)) {
|
|
945
|
-
const unsub = nodes[field].subscribe(() => {
|
|
946
|
-
run(buildSnapshot());
|
|
947
|
-
});
|
|
948
|
-
entrySubs.push(unsub);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
run(buildSnapshot());
|
|
952
|
-
};
|
|
953
|
-
const keysUnsub = keysNode.subscribe((msgs) => {
|
|
954
|
-
if (msgs.some((m) => m[0] === DATA || m[0] === RESOLVED)) {
|
|
955
|
-
sync(keysNode.cache ?? []);
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
sync(keysNode.cache ?? []);
|
|
959
|
-
return () => {
|
|
960
|
-
keysUnsub();
|
|
961
|
-
cleanupEntries();
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
// src/compat/vue/index.ts
|
|
968
|
-
var vue_exports = {};
|
|
969
|
-
__export(vue_exports, {
|
|
970
|
-
useStore: () => useStore4,
|
|
971
|
-
useSubscribe: () => useSubscribe4,
|
|
972
|
-
useSubscribeRecord: () => useSubscribeRecord4
|
|
973
|
-
});
|
|
291
|
+
} from "./chunk-PHOUUNK7.js";
|
|
974
292
|
import {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
const inner = shallowRef(node2.cache);
|
|
999
|
-
const unsub = node2.subscribe(() => {
|
|
1000
|
-
inner.value = node2.cache;
|
|
1001
|
-
});
|
|
1002
|
-
if (getCurrentScope()) {
|
|
1003
|
-
onScopeDispose(() => unsub());
|
|
1004
|
-
} else if (typeof console !== "undefined") {
|
|
1005
|
-
console.warn(
|
|
1006
|
-
"[graphrefly-ts] useStore called outside a Vue scope \u2014 subscription will not be auto-disposed."
|
|
1007
|
-
);
|
|
1008
|
-
}
|
|
1009
|
-
return computed2({
|
|
1010
|
-
get: () => inner.value,
|
|
1011
|
-
set: (v) => {
|
|
1012
|
-
node2.down([[DIRTY], [DATA, v]]);
|
|
1013
|
-
}
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
function useSubscribeRecord4(keys, factory) {
|
|
1017
|
-
const result = shallowRef({});
|
|
1018
|
-
const activeSubs = /* @__PURE__ */ new Map();
|
|
1019
|
-
function flushResult() {
|
|
1020
|
-
const snap = {};
|
|
1021
|
-
for (const [key, entry] of activeSubs) {
|
|
1022
|
-
snap[key] = { ...entry.values };
|
|
1023
|
-
}
|
|
1024
|
-
result.value = snap;
|
|
1025
|
-
}
|
|
1026
|
-
function sync(newKeys) {
|
|
1027
|
-
for (const entry of activeSubs.values()) {
|
|
1028
|
-
for (const unsub of entry.subs) unsub();
|
|
1029
|
-
}
|
|
1030
|
-
activeSubs.clear();
|
|
1031
|
-
for (const key of newKeys) {
|
|
1032
|
-
const nodes = factory(key);
|
|
1033
|
-
const fields = Object.keys(nodes);
|
|
1034
|
-
const values = {};
|
|
1035
|
-
const subs = [];
|
|
1036
|
-
for (const field of fields) {
|
|
1037
|
-
const node2 = nodes[field];
|
|
1038
|
-
values[field] = node2.cache;
|
|
1039
|
-
const unsub = node2.subscribe(() => {
|
|
1040
|
-
values[field] = node2.cache;
|
|
1041
|
-
flushResult();
|
|
1042
|
-
});
|
|
1043
|
-
subs.push(unsub);
|
|
1044
|
-
}
|
|
1045
|
-
activeSubs.set(key, { subs, values });
|
|
1046
|
-
}
|
|
1047
|
-
const snap = {};
|
|
1048
|
-
for (const [key, entry] of activeSubs) {
|
|
1049
|
-
snap[key] = { ...entry.values };
|
|
1050
|
-
}
|
|
1051
|
-
result.value = snap;
|
|
1052
|
-
}
|
|
1053
|
-
const readKeys = () => {
|
|
1054
|
-
const current = typeof keys === "function" ? keys() : isRef(keys) ? keys.value : keys;
|
|
1055
|
-
return [...current ?? []];
|
|
1056
|
-
};
|
|
1057
|
-
watch(readKeys, (newKeys) => sync(newKeys ?? []), { immediate: true });
|
|
1058
|
-
if (getCurrentScope()) {
|
|
1059
|
-
onScopeDispose(() => {
|
|
1060
|
-
for (const entry of activeSubs.values()) {
|
|
1061
|
-
for (const unsub of entry.subs) unsub();
|
|
1062
|
-
}
|
|
1063
|
-
activeSubs.clear();
|
|
1064
|
-
});
|
|
1065
|
-
} else if (typeof console !== "undefined") {
|
|
1066
|
-
console.warn(
|
|
1067
|
-
"[graphrefly-ts] useSubscribeRecord called outside a Vue scope \u2014 subscription will not be auto-disposed."
|
|
1068
|
-
);
|
|
1069
|
-
}
|
|
1070
|
-
return readonly(result);
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
// src/compat/zustand/index.ts
|
|
1074
|
-
var zustand_exports = {};
|
|
1075
|
-
__export(zustand_exports, {
|
|
1076
|
-
create: () => create
|
|
1077
|
-
});
|
|
1078
|
-
var alwaysDiffer = () => false;
|
|
1079
|
-
function create(initializer) {
|
|
1080
|
-
const g = new Graph("zustand");
|
|
1081
|
-
const s = state(void 0, {
|
|
1082
|
-
name: "state",
|
|
1083
|
-
equals: alwaysDiffer
|
|
1084
|
-
});
|
|
1085
|
-
g.add("state", s);
|
|
1086
|
-
const getState = () => s.cache;
|
|
1087
|
-
const setState = (partial, replace) => {
|
|
1088
|
-
const prev = s.cache;
|
|
1089
|
-
const next = typeof partial === "function" ? partial(prev) : partial;
|
|
1090
|
-
s.emit(replace ? next : { ...prev, ...next });
|
|
1091
|
-
};
|
|
1092
|
-
const api = {
|
|
1093
|
-
getState,
|
|
1094
|
-
setState,
|
|
1095
|
-
getInitialState: () => initialValue,
|
|
1096
|
-
subscribe: (listener) => {
|
|
1097
|
-
let initial = true;
|
|
1098
|
-
let prev = s.cache;
|
|
1099
|
-
return s.subscribe((msgs) => {
|
|
1100
|
-
for (const [t, v] of msgs) {
|
|
1101
|
-
if (t === DATA) {
|
|
1102
|
-
if (initial) {
|
|
1103
|
-
initial = false;
|
|
1104
|
-
continue;
|
|
1105
|
-
}
|
|
1106
|
-
listener(v, prev);
|
|
1107
|
-
prev = v;
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
});
|
|
1111
|
-
},
|
|
1112
|
-
destroy: g.destroy.bind(g)
|
|
1113
|
-
};
|
|
1114
|
-
const initialValue = initializer(setState, getState, api);
|
|
1115
|
-
s.emit(initialValue);
|
|
1116
|
-
return Object.assign(g, api);
|
|
1117
|
-
}
|
|
293
|
+
COMPLETE,
|
|
294
|
+
COMPLETE_MSG,
|
|
295
|
+
COMPLETE_ONLY_BATCH,
|
|
296
|
+
DATA,
|
|
297
|
+
DIRTY,
|
|
298
|
+
DIRTY_MSG,
|
|
299
|
+
DIRTY_ONLY_BATCH,
|
|
300
|
+
ERROR,
|
|
301
|
+
INVALIDATE,
|
|
302
|
+
INVALIDATE_MSG,
|
|
303
|
+
INVALIDATE_ONLY_BATCH,
|
|
304
|
+
PAUSE,
|
|
305
|
+
RESOLVED,
|
|
306
|
+
RESOLVED_MSG,
|
|
307
|
+
RESOLVED_ONLY_BATCH,
|
|
308
|
+
RESUME,
|
|
309
|
+
START,
|
|
310
|
+
START_MSG,
|
|
311
|
+
TEARDOWN,
|
|
312
|
+
TEARDOWN_MSG,
|
|
313
|
+
TEARDOWN_ONLY_BATCH,
|
|
314
|
+
__export
|
|
315
|
+
} from "./chunk-SX52TAR4.js";
|
|
1118
316
|
|
|
1119
317
|
// src/patterns/index.ts
|
|
1120
318
|
var patterns_exports = {};
|
|
1121
319
|
__export(patterns_exports, {
|
|
320
|
+
SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
|
|
321
|
+
SurfaceError: () => SurfaceError,
|
|
322
|
+
accountability: () => audit_exports,
|
|
1122
323
|
ai: () => ai_exports,
|
|
324
|
+
asSurfaceError: () => asSurfaceError,
|
|
1123
325
|
cqrs: () => cqrs_exports,
|
|
326
|
+
createGraph: () => createGraph,
|
|
327
|
+
deleteSnapshot: () => deleteSnapshot,
|
|
1124
328
|
demoShell: () => demo_shell_exports,
|
|
329
|
+
diffSnapshots: () => diffSnapshots,
|
|
1125
330
|
domainTemplates: () => domain_templates_exports,
|
|
1126
331
|
graphspec: () => graphspec_exports,
|
|
332
|
+
guarded: () => guarded_execution_exports,
|
|
1127
333
|
harness: () => harness_exports,
|
|
1128
334
|
layout: () => reactive_layout_exports,
|
|
335
|
+
lens: () => lens_exports,
|
|
336
|
+
listSnapshots: () => listSnapshots,
|
|
1129
337
|
memory: () => memory_exports,
|
|
1130
338
|
messaging: () => messaging_exports,
|
|
1131
339
|
orchestration: () => orchestration_exports,
|
|
1132
|
-
reduction: () => reduction_exports
|
|
340
|
+
reduction: () => reduction_exports,
|
|
341
|
+
resilientPipeline: () => resilient_pipeline_exports,
|
|
342
|
+
restoreSnapshot: () => restoreSnapshot,
|
|
343
|
+
runReduction: () => runReduction,
|
|
344
|
+
saveSnapshot: () => saveSnapshot,
|
|
345
|
+
surface: () => surface_exports
|
|
1133
346
|
});
|
|
1134
347
|
|
|
1135
348
|
// src/patterns/ai.ts
|
|
@@ -4167,308 +3380,418 @@ async function suggestStrategy(graph, problem, adapter, opts) {
|
|
|
4167
3380
|
};
|
|
4168
3381
|
}
|
|
4169
3382
|
|
|
4170
|
-
// src/patterns/
|
|
4171
|
-
var
|
|
4172
|
-
__export(
|
|
4173
|
-
|
|
3383
|
+
// src/patterns/audit.ts
|
|
3384
|
+
var audit_exports = {};
|
|
3385
|
+
__export(audit_exports, {
|
|
3386
|
+
AuditTrailGraph: () => AuditTrailGraph,
|
|
3387
|
+
PolicyEnforcerGraph: () => PolicyEnforcerGraph,
|
|
3388
|
+
auditTrail: () => auditTrail,
|
|
3389
|
+
complianceSnapshot: () => complianceSnapshot,
|
|
3390
|
+
policyEnforcer: () => policyEnforcer,
|
|
3391
|
+
reactiveExplainPath: () => reactiveExplainPath
|
|
4174
3392
|
});
|
|
4175
|
-
function
|
|
4176
|
-
return
|
|
4177
|
-
}
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
name
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
g.add("pane/fullscreen", paneFullscreen);
|
|
4196
|
-
g.add("viewport/width", viewportWidth);
|
|
4197
|
-
const paneMainWidth = derived(
|
|
4198
|
-
[paneMainRatio, viewportWidth, paneFullscreen],
|
|
4199
|
-
([ratio, vw, fs]) => {
|
|
4200
|
-
const r = ratio;
|
|
4201
|
-
const w = vw;
|
|
4202
|
-
const fullscreen = fs;
|
|
4203
|
-
if (fullscreen === "main") return w;
|
|
4204
|
-
if (fullscreen === "graph" || fullscreen === "code") return 0;
|
|
4205
|
-
return Math.round(w * r);
|
|
4206
|
-
},
|
|
4207
|
-
{ name: "pane/main-width" }
|
|
4208
|
-
);
|
|
4209
|
-
const paneSideWidth = derived(
|
|
4210
|
-
[paneMainWidth, viewportWidth, paneFullscreen],
|
|
4211
|
-
([main, vw, fs]) => {
|
|
4212
|
-
const fullscreen = fs;
|
|
4213
|
-
const w = vw;
|
|
4214
|
-
if (fullscreen === "main") return 0;
|
|
4215
|
-
if (fullscreen === "graph" || fullscreen === "code") return w;
|
|
4216
|
-
return w - main;
|
|
4217
|
-
},
|
|
4218
|
-
{ name: "pane/side-width" }
|
|
4219
|
-
);
|
|
4220
|
-
const paneGraphHeight = derived(
|
|
4221
|
-
[paneSideSplit, paneFullscreen],
|
|
4222
|
-
([split, fs]) => {
|
|
4223
|
-
const fullscreen = fs;
|
|
4224
|
-
if (fullscreen === "graph") return 1;
|
|
4225
|
-
if (fullscreen === "code") return 0;
|
|
4226
|
-
if (fullscreen === "main") return 0;
|
|
4227
|
-
return clamp01(split);
|
|
4228
|
-
},
|
|
4229
|
-
{ name: "pane/graph-height-ratio" }
|
|
4230
|
-
);
|
|
4231
|
-
const paneCodeHeight = derived(
|
|
4232
|
-
[paneGraphHeight, paneFullscreen],
|
|
4233
|
-
([graphH, fs]) => {
|
|
4234
|
-
const fullscreen = fs;
|
|
4235
|
-
if (fullscreen === "code") return 1;
|
|
4236
|
-
if (fullscreen === "graph" || fullscreen === "main") return 0;
|
|
4237
|
-
return 1 - graphH;
|
|
4238
|
-
},
|
|
4239
|
-
{ name: "pane/code-height-ratio" }
|
|
4240
|
-
);
|
|
4241
|
-
g.add("pane/main-width", paneMainWidth);
|
|
4242
|
-
g.add("pane/side-width", paneSideWidth);
|
|
4243
|
-
g.add("pane/graph-height-ratio", paneGraphHeight);
|
|
4244
|
-
g.add("pane/code-height-ratio", paneCodeHeight);
|
|
4245
|
-
const demoGraphRef = state(null, {
|
|
4246
|
-
name: "demo/graph-ref"
|
|
4247
|
-
});
|
|
4248
|
-
const demoGraphTick = state(0, { name: "demo/graph-tick" });
|
|
4249
|
-
g.add("demo/graph-ref", demoGraphRef);
|
|
4250
|
-
g.add("demo/graph-tick", demoGraphTick);
|
|
4251
|
-
const graphMermaid = derived(
|
|
4252
|
-
[demoGraphRef, demoGraphTick],
|
|
4253
|
-
([ref, _tick]) => {
|
|
4254
|
-
const demo = ref;
|
|
4255
|
-
if (!demo) return "";
|
|
4256
|
-
return demo.describe({ format: "mermaid" });
|
|
4257
|
-
},
|
|
4258
|
-
{ name: "graph/mermaid" }
|
|
4259
|
-
);
|
|
4260
|
-
const graphDescribe = derived(
|
|
4261
|
-
[demoGraphRef, demoGraphTick],
|
|
4262
|
-
([ref, _tick]) => {
|
|
4263
|
-
const demo = ref;
|
|
4264
|
-
if (!demo) return null;
|
|
4265
|
-
const { expand: _, ...snapshot } = demo.describe({ detail: "standard" });
|
|
4266
|
-
return snapshot;
|
|
4267
|
-
},
|
|
4268
|
-
{ name: "graph/describe" }
|
|
4269
|
-
);
|
|
4270
|
-
g.add("graph/mermaid", graphMermaid);
|
|
4271
|
-
g.add("graph/describe", graphDescribe);
|
|
4272
|
-
const hoverTarget = state(null, { name: "hover/target" });
|
|
4273
|
-
g.add("hover/target", hoverTarget);
|
|
4274
|
-
const highlightCodeScroll = derived(
|
|
4275
|
-
[hoverTarget],
|
|
4276
|
-
([target]) => {
|
|
4277
|
-
const t = target;
|
|
4278
|
-
if (!t) return null;
|
|
4279
|
-
const entry = registry.get(t.id);
|
|
4280
|
-
return entry ? entry.codeLine : null;
|
|
4281
|
-
},
|
|
4282
|
-
{ name: "highlight/code-scroll" }
|
|
4283
|
-
);
|
|
4284
|
-
const highlightVisual = derived(
|
|
4285
|
-
[hoverTarget],
|
|
4286
|
-
([target]) => {
|
|
4287
|
-
const t = target;
|
|
4288
|
-
if (!t) return null;
|
|
4289
|
-
const entry = registry.get(t.id);
|
|
4290
|
-
return entry ? entry.visualSelector : null;
|
|
4291
|
-
},
|
|
4292
|
-
{ name: "highlight/visual" }
|
|
4293
|
-
);
|
|
4294
|
-
const highlightGraph = derived(
|
|
4295
|
-
[hoverTarget],
|
|
4296
|
-
([target]) => {
|
|
4297
|
-
const t = target;
|
|
4298
|
-
if (!t) return null;
|
|
4299
|
-
return t.id;
|
|
4300
|
-
},
|
|
4301
|
-
{ name: "highlight/graph" }
|
|
4302
|
-
);
|
|
4303
|
-
g.add("highlight/code-scroll", highlightCodeScroll);
|
|
4304
|
-
g.add("highlight/visual", highlightVisual);
|
|
4305
|
-
g.add("highlight/graph", highlightGraph);
|
|
4306
|
-
if (onHighlight?.codeScroll) {
|
|
4307
|
-
const cb = onHighlight.codeScroll;
|
|
4308
|
-
const applyCodeScroll = effect([highlightCodeScroll], ([line]) => {
|
|
4309
|
-
cb(line);
|
|
3393
|
+
function auditMeta(kind, extra) {
|
|
3394
|
+
return domainMeta("audit", kind, extra);
|
|
3395
|
+
}
|
|
3396
|
+
var DEFAULT_INCLUDE_TYPES = /* @__PURE__ */ new Set([
|
|
3397
|
+
"data",
|
|
3398
|
+
"error",
|
|
3399
|
+
"complete",
|
|
3400
|
+
"teardown"
|
|
3401
|
+
]);
|
|
3402
|
+
var AuditTrailGraph = class extends Graph {
|
|
3403
|
+
entries;
|
|
3404
|
+
count;
|
|
3405
|
+
_log;
|
|
3406
|
+
_target;
|
|
3407
|
+
constructor(target, opts) {
|
|
3408
|
+
super(opts.name ?? `${target.name}_audit`, opts.graph);
|
|
3409
|
+
this._target = target;
|
|
3410
|
+
this._log = reactiveLog([], {
|
|
3411
|
+
name: "entries",
|
|
3412
|
+
...opts.maxSize != null ? { maxSize: opts.maxSize } : {}
|
|
4310
3413
|
});
|
|
4311
|
-
|
|
3414
|
+
this.entries = this._log.entries;
|
|
3415
|
+
this.add("entries", this.entries);
|
|
3416
|
+
this.count = derived(
|
|
3417
|
+
[this.entries],
|
|
3418
|
+
([snapshot]) => snapshot.length,
|
|
3419
|
+
{ name: "count", describeKind: "derived", meta: auditMeta("count") }
|
|
3420
|
+
);
|
|
3421
|
+
this.add("count", this.count);
|
|
3422
|
+
this.addDisposer(keepalive(this.count));
|
|
3423
|
+
const includeTypes = opts.includeTypes != null ? new Set(opts.includeTypes) : DEFAULT_INCLUDE_TYPES;
|
|
3424
|
+
const filter2 = opts.filter;
|
|
3425
|
+
let seq = 0;
|
|
3426
|
+
const handle = target.observe({ timeline: true, structured: true });
|
|
3427
|
+
const offEvent = handle.onEvent((event) => {
|
|
3428
|
+
if (event.type === "derived") return;
|
|
3429
|
+
const type = event.type;
|
|
3430
|
+
if (!includeTypes.has(type)) return;
|
|
3431
|
+
const path = event.path ?? "";
|
|
3432
|
+
const entry = {
|
|
3433
|
+
seq: seq++,
|
|
3434
|
+
timestamp_ns: event.timestamp_ns ?? monotonicNs(),
|
|
3435
|
+
wall_clock_ns: wallClockNs(),
|
|
3436
|
+
path,
|
|
3437
|
+
type
|
|
3438
|
+
};
|
|
3439
|
+
const node2 = path ? safeNode(target, path) : void 0;
|
|
3440
|
+
const lastMutation = node2?.lastMutation;
|
|
3441
|
+
if (lastMutation != null) entry.actor = lastMutation.actor;
|
|
3442
|
+
if (type === "data") entry.value = event.data;
|
|
3443
|
+
if (type === "error") entry.error = event.data;
|
|
3444
|
+
const reason = path ? safeAnnotation(target, path) : void 0;
|
|
3445
|
+
if (reason != null) entry.reason = reason;
|
|
3446
|
+
if (filter2 != null && !filter2(entry)) return;
|
|
3447
|
+
this._log.append(entry);
|
|
3448
|
+
});
|
|
3449
|
+
this.addDisposer(() => {
|
|
3450
|
+
offEvent();
|
|
3451
|
+
handle.dispose();
|
|
3452
|
+
});
|
|
3453
|
+
this.addDisposer(() => this._log.disposeAllViews());
|
|
3454
|
+
}
|
|
3455
|
+
/** All entries currently in the ring (snapshot). */
|
|
3456
|
+
all() {
|
|
3457
|
+
return this.entries.cache ?? [];
|
|
3458
|
+
}
|
|
3459
|
+
/** Entries matching `path`. Order preserved. */
|
|
3460
|
+
byNode(path) {
|
|
3461
|
+
return this.all().filter((e) => e.path === path);
|
|
3462
|
+
}
|
|
3463
|
+
/** Entries whose `actor.id` matches. Use `byActorType` for type filtering. */
|
|
3464
|
+
byActor(actorId) {
|
|
3465
|
+
return this.all().filter((e) => e.actor?.id === actorId);
|
|
3466
|
+
}
|
|
3467
|
+
/** Entries whose `actor.type` matches (e.g. `"llm"`, `"human"`). */
|
|
3468
|
+
byActorType(type) {
|
|
3469
|
+
return this.all().filter((e) => e.actor?.type === type);
|
|
3470
|
+
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Entries with `timestamp_ns` in `[start_ns, end_ns)` (end exclusive).
|
|
3473
|
+
* Omit `end_ns` to query open-ended.
|
|
3474
|
+
*/
|
|
3475
|
+
byTimeRange(start_ns, end_ns) {
|
|
3476
|
+
return this.all().filter((e) => {
|
|
3477
|
+
if (e.timestamp_ns < start_ns) return false;
|
|
3478
|
+
if (end_ns != null && e.timestamp_ns >= end_ns) return false;
|
|
3479
|
+
return true;
|
|
3480
|
+
});
|
|
3481
|
+
}
|
|
3482
|
+
/** Reference to the audited graph (escape hatch for tooling). */
|
|
3483
|
+
get target() {
|
|
3484
|
+
return this._target;
|
|
3485
|
+
}
|
|
3486
|
+
};
|
|
3487
|
+
function auditTrail(target, opts = {}) {
|
|
3488
|
+
return new AuditTrailGraph(target, opts);
|
|
3489
|
+
}
|
|
3490
|
+
var PolicyEnforcerGraph = class extends Graph {
|
|
3491
|
+
policies;
|
|
3492
|
+
violations;
|
|
3493
|
+
violationCount;
|
|
3494
|
+
_target;
|
|
3495
|
+
_mode;
|
|
3496
|
+
_currentGuard;
|
|
3497
|
+
constructor(target, policies, opts) {
|
|
3498
|
+
super(opts.name ?? `${target.name}_policy`, opts.graph);
|
|
3499
|
+
this._target = target;
|
|
3500
|
+
this._mode = opts.mode ?? "audit";
|
|
3501
|
+
const policiesNode = isNode(policies) ? policies : state(policies, { name: "policies" });
|
|
3502
|
+
this.policies = policiesNode;
|
|
3503
|
+
this.add("policies", this.policies);
|
|
3504
|
+
this.violations = new TopicGraph("violations", {
|
|
3505
|
+
retainedLimit: opts.violationsLimit ?? 1e3
|
|
3506
|
+
});
|
|
3507
|
+
this.mount("violations", this.violations);
|
|
3508
|
+
this.violationCount = derived(
|
|
3509
|
+
[this.violations.events],
|
|
3510
|
+
([snapshot]) => snapshot.length,
|
|
3511
|
+
{
|
|
3512
|
+
name: "violationCount",
|
|
3513
|
+
describeKind: "derived",
|
|
3514
|
+
meta: auditMeta("policy_violation_count")
|
|
3515
|
+
}
|
|
3516
|
+
);
|
|
3517
|
+
this.add("violationCount", this.violationCount);
|
|
3518
|
+
this.addDisposer(keepalive(this.violationCount));
|
|
3519
|
+
const initialRules = policiesNode.cache ?? [];
|
|
3520
|
+
let latestRules = initialRules;
|
|
3521
|
+
this._currentGuard = policyFromRules(latestRules);
|
|
3522
|
+
const offPolicies = policiesNode.subscribe((msgs) => {
|
|
3523
|
+
for (const m of msgs) {
|
|
3524
|
+
if (m[0] === DATA) {
|
|
3525
|
+
latestRules = m[1] ?? [];
|
|
3526
|
+
this._currentGuard = policyFromRules(latestRules);
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
});
|
|
3530
|
+
this.addDisposer(offPolicies);
|
|
3531
|
+
const paths = opts.paths != null ? [...opts.paths] : collectPaths(target);
|
|
3532
|
+
if (this._mode === "enforce") {
|
|
3533
|
+
const restorers = /* @__PURE__ */ new Map();
|
|
3534
|
+
const wrapAndPush = (path) => {
|
|
3535
|
+
if (restorers.has(path)) return;
|
|
3536
|
+
const node2 = safeNode(target, path);
|
|
3537
|
+
if (!(node2 instanceof NodeImpl)) return;
|
|
3538
|
+
const pathGuard = (actor, action) => {
|
|
3539
|
+
const ok = this._currentGuard(actor, action);
|
|
3540
|
+
if (!ok) {
|
|
3541
|
+
this._publishViolation(actor, action, path, "blocked");
|
|
3542
|
+
}
|
|
3543
|
+
return ok;
|
|
3544
|
+
};
|
|
3545
|
+
restorers.set(path, node2._pushGuard(pathGuard));
|
|
3546
|
+
};
|
|
3547
|
+
for (const path of paths) wrapAndPush(path);
|
|
3548
|
+
if (opts.paths == null) {
|
|
3549
|
+
const offTopology = watchTopologyTree(target, (event, emitter, prefix) => {
|
|
3550
|
+
if (event.kind === "added") {
|
|
3551
|
+
if (event.nodeKind === "node") {
|
|
3552
|
+
wrapAndPush(`${prefix}${event.name}`);
|
|
3553
|
+
} else {
|
|
3554
|
+
const child = emitter._mounts.get(event.name);
|
|
3555
|
+
if (!(child instanceof Graph)) return;
|
|
3556
|
+
const mountPrefix = `${prefix}${event.name}::`;
|
|
3557
|
+
const localPaths = collectPaths(child);
|
|
3558
|
+
for (const localPath of localPaths) {
|
|
3559
|
+
wrapAndPush(
|
|
3560
|
+
localPath === "" ? `${prefix}${event.name}` : `${mountPrefix}${localPath}`
|
|
3561
|
+
);
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
} else if (event.kind === "removed") {
|
|
3565
|
+
if (event.nodeKind === "node") {
|
|
3566
|
+
const qp = `${prefix}${event.name}`;
|
|
3567
|
+
const r = restorers.get(qp);
|
|
3568
|
+
if (r != null) {
|
|
3569
|
+
r();
|
|
3570
|
+
restorers.delete(qp);
|
|
3571
|
+
}
|
|
3572
|
+
} else {
|
|
3573
|
+
const mountQp = `${prefix}${event.name}`;
|
|
3574
|
+
const mountPrefix = `${mountQp}::`;
|
|
3575
|
+
for (const [p, r] of restorers) {
|
|
3576
|
+
if (p === mountQp || p.startsWith(mountPrefix)) {
|
|
3577
|
+
r();
|
|
3578
|
+
restorers.delete(p);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
});
|
|
3584
|
+
this.addDisposer(offTopology);
|
|
3585
|
+
} else {
|
|
3586
|
+
const offCleanup = target.topology.subscribe((msgs) => {
|
|
3587
|
+
for (const m of msgs) {
|
|
3588
|
+
if (m[0] !== DATA) continue;
|
|
3589
|
+
const event = m[1];
|
|
3590
|
+
if (event.kind !== "removed" || event.nodeKind !== "node") continue;
|
|
3591
|
+
const r = restorers.get(event.name);
|
|
3592
|
+
if (r != null) {
|
|
3593
|
+
r();
|
|
3594
|
+
restorers.delete(event.name);
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
});
|
|
3598
|
+
this.addDisposer(offCleanup);
|
|
3599
|
+
}
|
|
3600
|
+
this.addDisposer(() => {
|
|
3601
|
+
for (const r of restorers.values()) r();
|
|
3602
|
+
restorers.clear();
|
|
3603
|
+
});
|
|
3604
|
+
} else {
|
|
3605
|
+
const handle = target.observe({ timeline: true, structured: true });
|
|
3606
|
+
const off = handle.onEvent((event) => {
|
|
3607
|
+
if (event.type !== "data" && event.type !== "error") return;
|
|
3608
|
+
const path = event.path ?? "";
|
|
3609
|
+
if (!path) return;
|
|
3610
|
+
if (opts.paths != null && !opts.paths.includes(path)) return;
|
|
3611
|
+
const node2 = safeNode(target, path);
|
|
3612
|
+
const lastMutation = node2?.lastMutation;
|
|
3613
|
+
if (lastMutation == null) return;
|
|
3614
|
+
const action = "write";
|
|
3615
|
+
if (this._currentGuard(lastMutation.actor, action)) return;
|
|
3616
|
+
this._publishViolation(lastMutation.actor, action, path, "observed");
|
|
3617
|
+
});
|
|
3618
|
+
this.addDisposer(() => {
|
|
3619
|
+
off();
|
|
3620
|
+
handle.dispose();
|
|
3621
|
+
});
|
|
3622
|
+
}
|
|
4312
3623
|
}
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
3624
|
+
_publishViolation(actor, action, path, result) {
|
|
3625
|
+
this.violations.publish({
|
|
3626
|
+
timestamp_ns: monotonicNs(),
|
|
3627
|
+
wall_clock_ns: wallClockNs(),
|
|
3628
|
+
path,
|
|
3629
|
+
actor,
|
|
3630
|
+
action,
|
|
3631
|
+
mode: this._mode,
|
|
3632
|
+
result
|
|
4317
3633
|
});
|
|
4318
|
-
g.add("highlight/apply-visual", applyVisual);
|
|
4319
3634
|
}
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
3635
|
+
/** Snapshot of recorded violations. */
|
|
3636
|
+
all() {
|
|
3637
|
+
return this.violations.retained();
|
|
3638
|
+
}
|
|
3639
|
+
get mode() {
|
|
3640
|
+
return this._mode;
|
|
4326
3641
|
}
|
|
4327
|
-
|
|
4328
|
-
|
|
3642
|
+
get target() {
|
|
3643
|
+
return this._target;
|
|
3644
|
+
}
|
|
3645
|
+
};
|
|
3646
|
+
function policyEnforcer(target, policies, opts = {}) {
|
|
3647
|
+
return new PolicyEnforcerGraph(target, policies, opts);
|
|
3648
|
+
}
|
|
3649
|
+
function reactiveExplainPath(target, from, to, opts) {
|
|
3650
|
+
let v = 0;
|
|
3651
|
+
const version2 = state(v, { name: "explain_version" });
|
|
3652
|
+
const handle = target.observe({ timeline: true, structured: true });
|
|
3653
|
+
const off = handle.onEvent((event) => {
|
|
3654
|
+
const t = event.type;
|
|
3655
|
+
if (t !== "data" && t !== "error" && t !== "complete" && t !== "teardown") return;
|
|
3656
|
+
v += 1;
|
|
3657
|
+
version2.emit(v);
|
|
4329
3658
|
});
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
3659
|
+
const explainOpts = {
|
|
3660
|
+
...opts?.maxDepth != null ? { maxDepth: opts.maxDepth } : {},
|
|
3661
|
+
...opts?.findCycle === true ? { findCycle: true } : {}
|
|
3662
|
+
};
|
|
3663
|
+
const node2 = derived([version2], () => target.explain(from, to, explainOpts), {
|
|
3664
|
+
name: opts?.name ?? "explain",
|
|
3665
|
+
describeKind: "derived",
|
|
3666
|
+
equals: (a, b) => a.found === b.found && a.reason === b.reason && a.steps.length === b.steps.length && causalStepsEqual(a.steps, b.steps),
|
|
3667
|
+
meta: auditMeta("explain_path", { from, to })
|
|
3668
|
+
});
|
|
3669
|
+
const stopKeepalive = keepalive(node2);
|
|
3670
|
+
return {
|
|
3671
|
+
node: node2,
|
|
3672
|
+
dispose() {
|
|
3673
|
+
off();
|
|
3674
|
+
handle.dispose();
|
|
3675
|
+
stopKeepalive();
|
|
3676
|
+
}
|
|
3677
|
+
};
|
|
3678
|
+
}
|
|
3679
|
+
function causalStepsEqual(a, b) {
|
|
3680
|
+
for (let i = 0; i < a.length; i++) {
|
|
3681
|
+
const x = a[i];
|
|
3682
|
+
const y = b[i];
|
|
3683
|
+
if (x.path !== y.path) return false;
|
|
3684
|
+
if (x.type !== y.type) return false;
|
|
3685
|
+
if (x.status !== y.status) return false;
|
|
3686
|
+
if (x.hop !== y.hop) return false;
|
|
3687
|
+
if (x.dep_index !== y.dep_index) return false;
|
|
3688
|
+
if (x.reason !== y.reason) return false;
|
|
3689
|
+
if (x.value !== y.value) return false;
|
|
3690
|
+
if (x.lastMutation !== y.lastMutation) return false;
|
|
3691
|
+
const xv = x.v;
|
|
3692
|
+
const yv = y.v;
|
|
3693
|
+
if (xv !== yv) {
|
|
3694
|
+
if (xv == null || yv == null) return false;
|
|
3695
|
+
if (xv.id !== yv.id || xv.version !== yv.version) return false;
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
return true;
|
|
3699
|
+
}
|
|
3700
|
+
function complianceSnapshot(target, opts = {}) {
|
|
3701
|
+
const result = {
|
|
3702
|
+
format_version: 1,
|
|
3703
|
+
timestamp_ns: monotonicNs(),
|
|
3704
|
+
wall_clock_ns: wallClockNs(),
|
|
3705
|
+
graph: target.snapshot()
|
|
3706
|
+
};
|
|
3707
|
+
if (opts.actor != null) result.actor = opts.actor;
|
|
3708
|
+
if (opts.audit != null) {
|
|
3709
|
+
const entries = [...opts.audit.all()];
|
|
3710
|
+
result.audit = { count: entries.length, entries };
|
|
3711
|
+
}
|
|
3712
|
+
if (opts.policies != null) {
|
|
3713
|
+
const rules = opts.policies.policies.cache ?? [];
|
|
3714
|
+
result.policies = {
|
|
3715
|
+
mode: opts.policies.mode,
|
|
3716
|
+
rules,
|
|
3717
|
+
violations: [...opts.policies.all()]
|
|
3718
|
+
};
|
|
3719
|
+
}
|
|
3720
|
+
const fingerprint = computeFingerprint(result);
|
|
3721
|
+
return { ...result, fingerprint };
|
|
3722
|
+
}
|
|
3723
|
+
function isNode(x) {
|
|
3724
|
+
return typeof x === "object" && x !== null && "subscribe" in x;
|
|
3725
|
+
}
|
|
3726
|
+
function safeNode(target, path) {
|
|
3727
|
+
try {
|
|
3728
|
+
return target.node(path);
|
|
3729
|
+
} catch {
|
|
3730
|
+
return void 0;
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
function safeAnnotation(target, path) {
|
|
3734
|
+
try {
|
|
3735
|
+
return target.annotation(path);
|
|
3736
|
+
} catch {
|
|
3737
|
+
return void 0;
|
|
3738
|
+
}
|
|
3739
|
+
}
|
|
3740
|
+
function collectPaths(target) {
|
|
3741
|
+
const described = target.describe({ detail: "minimal" });
|
|
3742
|
+
return Object.keys(described.nodes);
|
|
3743
|
+
}
|
|
3744
|
+
function computeFingerprint(value) {
|
|
3745
|
+
return defaultHash(JSON.stringify(canonicalize(value)));
|
|
3746
|
+
}
|
|
3747
|
+
function canonicalize(value) {
|
|
3748
|
+
const stack = /* @__PURE__ */ new Set();
|
|
3749
|
+
const walk = (v) => {
|
|
3750
|
+
if (v === void 0) return { __undefined: true };
|
|
3751
|
+
if (v === null) return null;
|
|
3752
|
+
const t = typeof v;
|
|
3753
|
+
if (t === "bigint") return { __bigint: v.toString() };
|
|
3754
|
+
if (t !== "object") return v;
|
|
3755
|
+
const obj = v;
|
|
3756
|
+
if (stack.has(obj)) return { __circular: true };
|
|
3757
|
+
stack.add(obj);
|
|
3758
|
+
try {
|
|
3759
|
+
if (Array.isArray(obj)) {
|
|
3760
|
+
return obj.map(walk);
|
|
4344
3761
|
}
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
);
|
|
4348
|
-
const inspectTraceLog = derived(
|
|
4349
|
-
[demoGraphRef, demoGraphTick],
|
|
4350
|
-
([ref, _tick]) => {
|
|
4351
|
-
const demo = ref;
|
|
4352
|
-
if (!demo) return [];
|
|
4353
|
-
return demo.trace();
|
|
4354
|
-
},
|
|
4355
|
-
{ name: "inspect/trace-log" }
|
|
4356
|
-
);
|
|
4357
|
-
g.add("inspect/node-detail", inspectNodeDetail);
|
|
4358
|
-
g.add("inspect/trace-log", inspectTraceLog);
|
|
4359
|
-
const metaDebug = state(false, { name: "meta/debug" });
|
|
4360
|
-
g.add("meta/debug", metaDebug);
|
|
4361
|
-
const metaShellMermaid = derived(
|
|
4362
|
-
[metaDebug, demoGraphTick],
|
|
4363
|
-
([debug, _tick]) => {
|
|
4364
|
-
if (!debug) return "";
|
|
4365
|
-
return g.describe({ format: "mermaid" });
|
|
4366
|
-
},
|
|
4367
|
-
{ name: "meta/shell-mermaid" }
|
|
4368
|
-
);
|
|
4369
|
-
g.add("meta/shell-mermaid", metaShellMermaid);
|
|
4370
|
-
const codeTextNode = state("", { name: "layout/code-text" });
|
|
4371
|
-
g.add("layout/code-text", codeTextNode);
|
|
4372
|
-
if (adapter) {
|
|
4373
|
-
const measureCache = /* @__PURE__ */ new Map();
|
|
4374
|
-
const graphLabels = derived(
|
|
4375
|
-
[graphDescribe],
|
|
4376
|
-
([desc]) => {
|
|
4377
|
-
const d = desc;
|
|
4378
|
-
if (!d) return /* @__PURE__ */ new Map();
|
|
4379
|
-
const result = /* @__PURE__ */ new Map();
|
|
4380
|
-
for (const [name] of Object.entries(d.nodes)) {
|
|
4381
|
-
const segments = analyzeAndMeasure(name, layoutFont, adapter, measureCache);
|
|
4382
|
-
const lb = computeLineBreaks(segments, Infinity, adapter, layoutFont, measureCache);
|
|
4383
|
-
const width = lb.lines.reduce((max, l) => Math.max(max, l.width), 0);
|
|
4384
|
-
const height = lb.lineCount * 20;
|
|
4385
|
-
result.set(name, { width, height });
|
|
4386
|
-
}
|
|
4387
|
-
return result;
|
|
4388
|
-
},
|
|
4389
|
-
{
|
|
4390
|
-
name: "layout/graph-labels",
|
|
4391
|
-
equals: (a, b) => {
|
|
4392
|
-
if (a === b) return true;
|
|
4393
|
-
const ma = a;
|
|
4394
|
-
const mb = b;
|
|
4395
|
-
if (ma.size !== mb.size) return false;
|
|
4396
|
-
for (const [k, v] of ma) {
|
|
4397
|
-
const bv = mb.get(k);
|
|
4398
|
-
if (!bv || bv.width !== v.width || bv.height !== v.height) return false;
|
|
4399
|
-
}
|
|
4400
|
-
return true;
|
|
4401
|
-
}
|
|
3762
|
+
if (obj instanceof Date) {
|
|
3763
|
+
return { __date: obj.toISOString() };
|
|
4402
3764
|
}
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
(
|
|
4407
|
-
const
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
return
|
|
4412
|
-
}
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
(
|
|
4418
|
-
const
|
|
4419
|
-
|
|
4420
|
-
let
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
g.add("layout/side-width-hint", sideWidthHint);
|
|
4431
|
-
}
|
|
4432
|
-
let tickCounter = 0;
|
|
4433
|
-
return {
|
|
4434
|
-
graph: g,
|
|
4435
|
-
setMainRatio(ratio) {
|
|
4436
|
-
g.set("pane/main-ratio", clamp01(ratio));
|
|
4437
|
-
},
|
|
4438
|
-
setSideSplit(ratio) {
|
|
4439
|
-
g.set("pane/side-split", clamp01(ratio));
|
|
4440
|
-
},
|
|
4441
|
-
setFullscreen(pane) {
|
|
4442
|
-
g.set("pane/fullscreen", pane);
|
|
4443
|
-
},
|
|
4444
|
-
setViewportWidth(width) {
|
|
4445
|
-
g.set("viewport/width", Math.max(0, width));
|
|
4446
|
-
},
|
|
4447
|
-
setHoverTarget(target) {
|
|
4448
|
-
g.set("hover/target", target);
|
|
4449
|
-
},
|
|
4450
|
-
setDemoGraph(demo) {
|
|
4451
|
-
g.set("demo/graph-ref", demo);
|
|
4452
|
-
},
|
|
4453
|
-
bumpGraphTick() {
|
|
4454
|
-
g.set("demo/graph-tick", ++tickCounter);
|
|
4455
|
-
},
|
|
4456
|
-
selectNode(path) {
|
|
4457
|
-
g.set("inspect/selected-node", path);
|
|
4458
|
-
},
|
|
4459
|
-
setMetaDebug(on) {
|
|
4460
|
-
g.set("meta/debug", on);
|
|
4461
|
-
},
|
|
4462
|
-
setCodeText(text) {
|
|
4463
|
-
g.set("layout/code-text", text);
|
|
4464
|
-
},
|
|
4465
|
-
batch(fn) {
|
|
4466
|
-
batch(fn);
|
|
4467
|
-
},
|
|
4468
|
-
destroy() {
|
|
4469
|
-
g.destroy();
|
|
3765
|
+
if (obj instanceof RegExp) {
|
|
3766
|
+
return { __regexp: { source: obj.source, flags: obj.flags } };
|
|
3767
|
+
}
|
|
3768
|
+
if (obj instanceof Map) {
|
|
3769
|
+
const entries = [...obj.entries()].map(([k, mv]) => [
|
|
3770
|
+
walk(k),
|
|
3771
|
+
walk(mv)
|
|
3772
|
+
]);
|
|
3773
|
+
return { __map: entries };
|
|
3774
|
+
}
|
|
3775
|
+
if (obj instanceof Set) {
|
|
3776
|
+
const items = [...obj].map(walk);
|
|
3777
|
+
return { __set: items };
|
|
3778
|
+
}
|
|
3779
|
+
if (ArrayBuffer.isView(obj)) {
|
|
3780
|
+
const ta = obj;
|
|
3781
|
+
const arr = new Array(ta.length);
|
|
3782
|
+
for (let i = 0; i < ta.length; i++) arr[i] = ta[i] ?? 0;
|
|
3783
|
+
return { __typed_array: { ctor: obj.constructor.name, data: arr } };
|
|
3784
|
+
}
|
|
3785
|
+
const out = {};
|
|
3786
|
+
for (const k of Object.keys(obj).sort()) {
|
|
3787
|
+
out[k] = walk(obj[k]);
|
|
3788
|
+
}
|
|
3789
|
+
return out;
|
|
3790
|
+
} finally {
|
|
3791
|
+
stack.delete(obj);
|
|
4470
3792
|
}
|
|
4471
3793
|
};
|
|
3794
|
+
return walk(value);
|
|
4472
3795
|
}
|
|
4473
3796
|
|
|
4474
3797
|
// src/patterns/domain-templates.ts
|
|
@@ -6301,6 +5624,65 @@ ${validation.errors.join("\n")}`);
|
|
|
6301
5624
|
return parsed;
|
|
6302
5625
|
}
|
|
6303
5626
|
|
|
5627
|
+
// src/patterns/guarded-execution.ts
|
|
5628
|
+
var guarded_execution_exports = {};
|
|
5629
|
+
__export(guarded_execution_exports, {
|
|
5630
|
+
GuardedExecutionGraph: () => GuardedExecutionGraph,
|
|
5631
|
+
guardedExecution: () => guardedExecution
|
|
5632
|
+
});
|
|
5633
|
+
var GuardedExecutionGraph = class extends Graph {
|
|
5634
|
+
enforcer;
|
|
5635
|
+
violations;
|
|
5636
|
+
_target;
|
|
5637
|
+
_defaultActor;
|
|
5638
|
+
constructor(target, opts) {
|
|
5639
|
+
super(opts.name ?? `${target.name}_guarded`, opts.graph);
|
|
5640
|
+
this._target = target;
|
|
5641
|
+
this._defaultActor = opts.actor;
|
|
5642
|
+
const enforcerOpts = {
|
|
5643
|
+
mode: opts.mode ?? "enforce",
|
|
5644
|
+
name: "enforcer"
|
|
5645
|
+
};
|
|
5646
|
+
if (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;
|
|
5647
|
+
this.enforcer = policyEnforcer(target, opts.policies, enforcerOpts);
|
|
5648
|
+
this.violations = this.enforcer.violations;
|
|
5649
|
+
this.mount("enforcer", this.enforcer);
|
|
5650
|
+
}
|
|
5651
|
+
/**
|
|
5652
|
+
* Describe the **target** graph scoped to the configured actor. Returns
|
|
5653
|
+
* only nodes the actor is permitted to see (via the target's node guards
|
|
5654
|
+
* filtering `describe()` via `actor`).
|
|
5655
|
+
*
|
|
5656
|
+
* Pass `{actor}` in opts to override the configured actor for this call.
|
|
5657
|
+
* Pass any standard {@link GraphDescribeOptions} fields (`detail`,
|
|
5658
|
+
* `fields`, `filter`) — they apply to the target's describe.
|
|
5659
|
+
*
|
|
5660
|
+
* **Mode interaction:**
|
|
5661
|
+
* - In `mode: "enforce"` (default), the enforcer stacks a policy-derived
|
|
5662
|
+
* guard on every target node. `scopedDescribe({actor})` then filters by
|
|
5663
|
+
* the AND of per-node guards AND the stacked policy guard.
|
|
5664
|
+
* - In `mode: "audit"`, NO guards are stacked — `scopedDescribe` filters
|
|
5665
|
+
* purely by the target's pre-existing per-node guards. If a target has
|
|
5666
|
+
* no node-level guards, the policy rules you pass have no effect on
|
|
5667
|
+
* visibility (they only populate the `violations` topic on writes).
|
|
5668
|
+
*/
|
|
5669
|
+
scopedDescribe(opts) {
|
|
5670
|
+
const actor = opts?.actor ?? this._defaultActor;
|
|
5671
|
+
const describeOpts = {
|
|
5672
|
+
...opts,
|
|
5673
|
+
...actor != null ? { actor } : {}
|
|
5674
|
+
};
|
|
5675
|
+
return this._target.describe(describeOpts);
|
|
5676
|
+
}
|
|
5677
|
+
/** The wrapped graph (escape hatch for tooling). */
|
|
5678
|
+
get target() {
|
|
5679
|
+
return this._target;
|
|
5680
|
+
}
|
|
5681
|
+
};
|
|
5682
|
+
function guardedExecution(target, opts) {
|
|
5683
|
+
return new GuardedExecutionGraph(target, opts);
|
|
5684
|
+
}
|
|
5685
|
+
|
|
6304
5686
|
// src/patterns/harness/index.ts
|
|
6305
5687
|
var harness_exports = {};
|
|
6306
5688
|
__export(harness_exports, {
|
|
@@ -6379,8 +5761,8 @@ function evalIntakeBridge(evalSource2, intakeTopic, opts) {
|
|
|
6379
5761
|
{ name: opts?.name ?? "eval-intake-bridge" }
|
|
6380
5762
|
);
|
|
6381
5763
|
}
|
|
6382
|
-
function evalSource(
|
|
6383
|
-
return switchMap(
|
|
5764
|
+
function evalSource(trigger, runner) {
|
|
5765
|
+
return switchMap(trigger, () => fromAny(runner()));
|
|
6384
5766
|
}
|
|
6385
5767
|
function beforeAfterCompare(before, after) {
|
|
6386
5768
|
return derived(
|
|
@@ -6982,6 +6364,636 @@ function truncate(s, max) {
|
|
|
6982
6364
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
6983
6365
|
}
|
|
6984
6366
|
|
|
6367
|
+
// src/patterns/lens.ts
|
|
6368
|
+
var lens_exports = {};
|
|
6369
|
+
__export(lens_exports, {
|
|
6370
|
+
LensGraph: () => LensGraph,
|
|
6371
|
+
graphLens: () => graphLens,
|
|
6372
|
+
watchTopologyTree: () => watchTopologyTree
|
|
6373
|
+
});
|
|
6374
|
+
function lensMeta(kind) {
|
|
6375
|
+
return domainMeta("lens", kind);
|
|
6376
|
+
}
|
|
6377
|
+
function computeTopologyStats(described) {
|
|
6378
|
+
const paths = Object.keys(described.nodes);
|
|
6379
|
+
const depsByPath = /* @__PURE__ */ new Map();
|
|
6380
|
+
const dependents = /* @__PURE__ */ new Map();
|
|
6381
|
+
for (const path of paths) {
|
|
6382
|
+
const deps = described.nodes[path]?.deps ?? [];
|
|
6383
|
+
depsByPath.set(path, deps);
|
|
6384
|
+
for (const dep of deps) {
|
|
6385
|
+
if (!dependents.has(dep)) dependents.set(dep, /* @__PURE__ */ new Set());
|
|
6386
|
+
dependents.get(dep).add(path);
|
|
6387
|
+
}
|
|
6388
|
+
}
|
|
6389
|
+
const sources = [];
|
|
6390
|
+
const sinks = [];
|
|
6391
|
+
for (const path of paths) {
|
|
6392
|
+
if ((depsByPath.get(path) ?? []).length === 0) sources.push(path);
|
|
6393
|
+
if (!dependents.has(path)) sinks.push(path);
|
|
6394
|
+
}
|
|
6395
|
+
sources.sort();
|
|
6396
|
+
sinks.sort();
|
|
6397
|
+
const edgeCount = described.edges.length;
|
|
6398
|
+
const WHITE = 0;
|
|
6399
|
+
const GRAY = 1;
|
|
6400
|
+
const BLACK = 2;
|
|
6401
|
+
const color = /* @__PURE__ */ new Map();
|
|
6402
|
+
for (const p of paths) color.set(p, WHITE);
|
|
6403
|
+
let hasCycles = false;
|
|
6404
|
+
const longestFrom = /* @__PURE__ */ new Map();
|
|
6405
|
+
const dfs = (path) => {
|
|
6406
|
+
const c = color.get(path) ?? WHITE;
|
|
6407
|
+
if (c === GRAY) {
|
|
6408
|
+
hasCycles = true;
|
|
6409
|
+
return 0;
|
|
6410
|
+
}
|
|
6411
|
+
if (c === BLACK) return longestFrom.get(path) ?? 0;
|
|
6412
|
+
color.set(path, GRAY);
|
|
6413
|
+
let best = 0;
|
|
6414
|
+
const kids = dependents.get(path);
|
|
6415
|
+
if (kids != null) {
|
|
6416
|
+
for (const k of kids) {
|
|
6417
|
+
const childLongest = dfs(k);
|
|
6418
|
+
if (childLongest + 1 > best) best = childLongest + 1;
|
|
6419
|
+
}
|
|
6420
|
+
}
|
|
6421
|
+
color.set(path, BLACK);
|
|
6422
|
+
longestFrom.set(path, best);
|
|
6423
|
+
return best;
|
|
6424
|
+
};
|
|
6425
|
+
let depth = 0;
|
|
6426
|
+
for (const src of sources) {
|
|
6427
|
+
const d = dfs(src);
|
|
6428
|
+
if (d > depth) depth = d;
|
|
6429
|
+
}
|
|
6430
|
+
for (const p of paths) {
|
|
6431
|
+
if (color.get(p) === WHITE) dfs(p);
|
|
6432
|
+
}
|
|
6433
|
+
return {
|
|
6434
|
+
nodeCount: paths.length,
|
|
6435
|
+
edgeCount,
|
|
6436
|
+
subgraphCount: described.subgraphs.length,
|
|
6437
|
+
sources,
|
|
6438
|
+
sinks,
|
|
6439
|
+
depth,
|
|
6440
|
+
hasCycles
|
|
6441
|
+
};
|
|
6442
|
+
}
|
|
6443
|
+
function computeHealthReport(described) {
|
|
6444
|
+
const problems = [];
|
|
6445
|
+
for (const [path, desc] of Object.entries(described.nodes)) {
|
|
6446
|
+
if (desc.status !== "errored") continue;
|
|
6447
|
+
const entry = { path, status: "errored" };
|
|
6448
|
+
const upstream = reachable(described, path, "upstream", {});
|
|
6449
|
+
for (const p of upstream) {
|
|
6450
|
+
if (p === path) continue;
|
|
6451
|
+
if (described.nodes[p]?.status === "errored") {
|
|
6452
|
+
entry.upstreamCause = p;
|
|
6453
|
+
break;
|
|
6454
|
+
}
|
|
6455
|
+
}
|
|
6456
|
+
problems.push(entry);
|
|
6457
|
+
}
|
|
6458
|
+
problems.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
6459
|
+
return { ok: problems.length === 0, problems };
|
|
6460
|
+
}
|
|
6461
|
+
function topologyStatsEqual(a, b) {
|
|
6462
|
+
return a.nodeCount === b.nodeCount && a.edgeCount === b.edgeCount && a.subgraphCount === b.subgraphCount && a.depth === b.depth && a.hasCycles === b.hasCycles && stringArrayEqual(a.sources, b.sources) && stringArrayEqual(a.sinks, b.sinks);
|
|
6463
|
+
}
|
|
6464
|
+
function healthReportEqual(a, b) {
|
|
6465
|
+
if (a.ok !== b.ok) return false;
|
|
6466
|
+
if (a.problems.length !== b.problems.length) return false;
|
|
6467
|
+
for (let i = 0; i < a.problems.length; i++) {
|
|
6468
|
+
const x = a.problems[i];
|
|
6469
|
+
const y = b.problems[i];
|
|
6470
|
+
if (x.path !== y.path) return false;
|
|
6471
|
+
if (x.status !== y.status) return false;
|
|
6472
|
+
if (x.upstreamCause !== y.upstreamCause) return false;
|
|
6473
|
+
}
|
|
6474
|
+
return true;
|
|
6475
|
+
}
|
|
6476
|
+
function stringArrayEqual(a, b) {
|
|
6477
|
+
if (a.length !== b.length) return false;
|
|
6478
|
+
for (let i = 0; i < a.length; i++) {
|
|
6479
|
+
if (a[i] !== b[i]) return false;
|
|
6480
|
+
}
|
|
6481
|
+
return true;
|
|
6482
|
+
}
|
|
6483
|
+
var LensGraph = class extends Graph {
|
|
6484
|
+
/**
|
|
6485
|
+
* Aggregate structural stats — `nodeCount`, `edgeCount`, `sources`,
|
|
6486
|
+
* `sinks`, `depth`, `hasCycles`, `subgraphCount`. Recomputes on every
|
|
6487
|
+
* structural change via {@link watchTopologyTree} (transitive).
|
|
6488
|
+
*
|
|
6489
|
+
* Named `stats` (not `topology`) because `Graph.topology` already names
|
|
6490
|
+
* the raw `TopologyEvent` stream on every graph including `LensGraph`;
|
|
6491
|
+
* giving the lens its own `topology` accessor with an incompatible
|
|
6492
|
+
* `Node<TopologyStats>` type would break Liskov substitutability.
|
|
6493
|
+
*/
|
|
6494
|
+
stats;
|
|
6495
|
+
health;
|
|
6496
|
+
/**
|
|
6497
|
+
* Per-path flow tracker — a live {@link ReactiveMapBundle} keyed by
|
|
6498
|
+
* qualified path. Use `.get(path)` / `.has(path)` / `.size` for O(1)
|
|
6499
|
+
* sync queries; subscribe to `.entries` for a reactive snapshot of the
|
|
6500
|
+
* whole map. Lazy — the snapshot is materialized only while `.entries`
|
|
6501
|
+
* has subscribers.
|
|
6502
|
+
*
|
|
6503
|
+
* Shape intentionally differs from `stats` / `health` (which are plain
|
|
6504
|
+
* `Node<Report>`) because `flow` is a keyed collection, not a single
|
|
6505
|
+
* aggregate value. The map shape exposes cheaper queries than any
|
|
6506
|
+
* snapshot-based design.
|
|
6507
|
+
*/
|
|
6508
|
+
flow;
|
|
6509
|
+
_target;
|
|
6510
|
+
constructor(target, opts = {}) {
|
|
6511
|
+
super(opts.name ?? `${target.name}_lens`, opts.graph);
|
|
6512
|
+
this._target = target;
|
|
6513
|
+
let statsVersion = 0;
|
|
6514
|
+
let healthVersion = 0;
|
|
6515
|
+
const statsTick = state(0, { name: "stats_tick" });
|
|
6516
|
+
const healthTick = state(0, { name: "health_tick" });
|
|
6517
|
+
this.add("stats_tick", statsTick);
|
|
6518
|
+
this.add("health_tick", healthTick);
|
|
6519
|
+
const mapOpts = { name: "flow" };
|
|
6520
|
+
if (opts.maxFlowPaths != null) mapOpts.maxSize = opts.maxFlowPaths;
|
|
6521
|
+
this.flow = reactiveMap(mapOpts);
|
|
6522
|
+
this.add("flow", this.flow.entries);
|
|
6523
|
+
const pathFilter = opts.pathFilter;
|
|
6524
|
+
const offTopology = watchTopologyTree(target, (event, _emitter, prefix) => {
|
|
6525
|
+
statsVersion += 1;
|
|
6526
|
+
statsTick.emit(statsVersion);
|
|
6527
|
+
healthVersion += 1;
|
|
6528
|
+
healthTick.emit(healthVersion);
|
|
6529
|
+
if (event.kind === "removed") {
|
|
6530
|
+
if (event.nodeKind === "node") {
|
|
6531
|
+
const qp = `${prefix}${event.name}`;
|
|
6532
|
+
this.flow.delete(qp);
|
|
6533
|
+
} else {
|
|
6534
|
+
const mountPrefix = `${prefix}${event.name}::`;
|
|
6535
|
+
const keysToDelete = [];
|
|
6536
|
+
for (const relativePath of event.audit.nodes) {
|
|
6537
|
+
const qualified = relativePath === "" ? `${prefix}${event.name}` : `${mountPrefix}${relativePath}`;
|
|
6538
|
+
keysToDelete.push(qualified);
|
|
6539
|
+
}
|
|
6540
|
+
if (keysToDelete.length > 0) this.flow.deleteMany(keysToDelete);
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
});
|
|
6544
|
+
this.addDisposer(offTopology);
|
|
6545
|
+
const observeHandle = target.observe({ timeline: true, structured: true });
|
|
6546
|
+
const offObserve = observeHandle.onEvent((event) => {
|
|
6547
|
+
const t = event.type;
|
|
6548
|
+
if (t === "error" || t === "complete" || t === "data" || t === "teardown") {
|
|
6549
|
+
healthVersion += 1;
|
|
6550
|
+
healthTick.emit(healthVersion);
|
|
6551
|
+
}
|
|
6552
|
+
if (t === "data") {
|
|
6553
|
+
const path = event.path ?? "";
|
|
6554
|
+
if (!path) return;
|
|
6555
|
+
if (pathFilter != null && !pathFilter(path)) return;
|
|
6556
|
+
const existing = this.flow.get(path);
|
|
6557
|
+
const count = existing != null ? existing.count + 1 : 1;
|
|
6558
|
+
this.flow.set(path, { path, count, lastUpdate_ns: monotonicNs() });
|
|
6559
|
+
}
|
|
6560
|
+
});
|
|
6561
|
+
this.addDisposer(() => {
|
|
6562
|
+
offObserve();
|
|
6563
|
+
observeHandle.dispose();
|
|
6564
|
+
});
|
|
6565
|
+
this.stats = derived(
|
|
6566
|
+
[statsTick],
|
|
6567
|
+
() => computeTopologyStats(target.describe({ detail: "minimal" })),
|
|
6568
|
+
{
|
|
6569
|
+
name: "stats",
|
|
6570
|
+
describeKind: "derived",
|
|
6571
|
+
equals: topologyStatsEqual,
|
|
6572
|
+
meta: lensMeta("stats")
|
|
6573
|
+
}
|
|
6574
|
+
);
|
|
6575
|
+
this.add("stats", this.stats);
|
|
6576
|
+
this.addDisposer(keepalive(this.stats));
|
|
6577
|
+
this.health = derived(
|
|
6578
|
+
[healthTick],
|
|
6579
|
+
() => computeHealthReport(target.describe({ detail: "standard" })),
|
|
6580
|
+
{
|
|
6581
|
+
name: "health",
|
|
6582
|
+
describeKind: "derived",
|
|
6583
|
+
equals: healthReportEqual,
|
|
6584
|
+
meta: lensMeta("health")
|
|
6585
|
+
}
|
|
6586
|
+
);
|
|
6587
|
+
this.add("health", this.health);
|
|
6588
|
+
this.addDisposer(keepalive(this.health));
|
|
6589
|
+
}
|
|
6590
|
+
/**
|
|
6591
|
+
* Live causal chain from `from` to `to`. Recomputes whenever the target
|
|
6592
|
+
* mutates. Disposed automatically when the lens is destroyed.
|
|
6593
|
+
*
|
|
6594
|
+
* **Lifetime note:** every call to `why()` registers a lens-owned disposer
|
|
6595
|
+
* that runs on `lens.destroy()`. The returned `dispose` function releases
|
|
6596
|
+
* the internal subscription but does NOT remove the lens-owned disposer —
|
|
6597
|
+
* so heavy calling (e.g. per render frame) accumulates no-op disposers
|
|
6598
|
+
* until lens teardown. Cache the returned handle for long-lived queries.
|
|
6599
|
+
*
|
|
6600
|
+
* @param from - Qualified path of the upstream endpoint.
|
|
6601
|
+
* @param to - Qualified path of the downstream endpoint.
|
|
6602
|
+
* @param opts - See {@link reactiveExplainPath}.
|
|
6603
|
+
*/
|
|
6604
|
+
why(from, to, opts) {
|
|
6605
|
+
const handle = reactiveExplainPath(this._target, from, to, opts);
|
|
6606
|
+
this.addDisposer(handle.dispose);
|
|
6607
|
+
return handle;
|
|
6608
|
+
}
|
|
6609
|
+
/** Reference to the lensed graph. */
|
|
6610
|
+
get target() {
|
|
6611
|
+
return this._target;
|
|
6612
|
+
}
|
|
6613
|
+
};
|
|
6614
|
+
function graphLens(target, opts) {
|
|
6615
|
+
return new LensGraph(target, opts);
|
|
6616
|
+
}
|
|
6617
|
+
|
|
6618
|
+
// src/patterns/resilient-pipeline.ts
|
|
6619
|
+
var resilient_pipeline_exports = {};
|
|
6620
|
+
__export(resilient_pipeline_exports, {
|
|
6621
|
+
NS_PER_MS: () => NS_PER_MS,
|
|
6622
|
+
NS_PER_SEC: () => NS_PER_SEC,
|
|
6623
|
+
resilientPipeline: () => resilientPipeline
|
|
6624
|
+
});
|
|
6625
|
+
function resilientPipeline(source, opts = {}) {
|
|
6626
|
+
let current = source;
|
|
6627
|
+
if (opts.rateLimit != null) {
|
|
6628
|
+
current = rateLimiter(current, opts.rateLimit);
|
|
6629
|
+
}
|
|
6630
|
+
if (opts.budget != null && opts.budget.length > 0) {
|
|
6631
|
+
current = budgetGate(current, opts.budget);
|
|
6632
|
+
}
|
|
6633
|
+
let breakerState;
|
|
6634
|
+
if (opts.breaker != null) {
|
|
6635
|
+
const breaker = circuitBreaker(opts.breaker);
|
|
6636
|
+
const onOpen = opts.breakerOnOpen ?? "skip";
|
|
6637
|
+
const wrapped = withBreaker(breaker, { onOpen })(current);
|
|
6638
|
+
current = wrapped.node;
|
|
6639
|
+
breakerState = wrapped.breakerState;
|
|
6640
|
+
}
|
|
6641
|
+
if (opts.timeoutMs != null) {
|
|
6642
|
+
if (opts.timeoutMs <= 0) throw new RangeError("timeoutMs must be > 0");
|
|
6643
|
+
if (opts.timeoutMs > 9e6) {
|
|
6644
|
+
throw new RangeError(
|
|
6645
|
+
"timeoutMs must be <= 9_000_000 (\u22482.5h) to stay within safe ns arithmetic"
|
|
6646
|
+
);
|
|
6647
|
+
}
|
|
6648
|
+
current = timeout(current, opts.timeoutMs * NS_PER_MS);
|
|
6649
|
+
}
|
|
6650
|
+
if (opts.retry != null) {
|
|
6651
|
+
current = retry(current, opts.retry);
|
|
6652
|
+
}
|
|
6653
|
+
if (opts.fallback !== void 0) {
|
|
6654
|
+
current = fallback(current, opts.fallback);
|
|
6655
|
+
}
|
|
6656
|
+
const withStatusBundle = withStatus(current, { initialStatus: opts.initialStatus ?? "pending" });
|
|
6657
|
+
return {
|
|
6658
|
+
node: withStatusBundle.node,
|
|
6659
|
+
status: withStatusBundle.status,
|
|
6660
|
+
error: withStatusBundle.error,
|
|
6661
|
+
breakerState
|
|
6662
|
+
};
|
|
6663
|
+
}
|
|
6664
|
+
|
|
6665
|
+
// src/patterns/surface/index.ts
|
|
6666
|
+
var surface_exports = {};
|
|
6667
|
+
__export(surface_exports, {
|
|
6668
|
+
SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
|
|
6669
|
+
SurfaceError: () => SurfaceError,
|
|
6670
|
+
asSurfaceError: () => asSurfaceError,
|
|
6671
|
+
createGraph: () => createGraph,
|
|
6672
|
+
deleteSnapshot: () => deleteSnapshot,
|
|
6673
|
+
diffSnapshots: () => diffSnapshots,
|
|
6674
|
+
listSnapshots: () => listSnapshots,
|
|
6675
|
+
restoreSnapshot: () => restoreSnapshot,
|
|
6676
|
+
runReduction: () => runReduction,
|
|
6677
|
+
saveSnapshot: () => saveSnapshot
|
|
6678
|
+
});
|
|
6679
|
+
|
|
6680
|
+
// src/patterns/surface/errors.ts
|
|
6681
|
+
var SurfaceError = class extends Error {
|
|
6682
|
+
code;
|
|
6683
|
+
details;
|
|
6684
|
+
constructor(code, message, details) {
|
|
6685
|
+
super(message);
|
|
6686
|
+
this.name = "SurfaceError";
|
|
6687
|
+
this.code = code;
|
|
6688
|
+
if (details !== void 0) this.details = details;
|
|
6689
|
+
}
|
|
6690
|
+
/**
|
|
6691
|
+
* JSON-safe payload for wire serialization. Defensively validates
|
|
6692
|
+
* `details` — if it can't be round-tripped through `JSON.stringify`
|
|
6693
|
+
* (cyclic refs, `BigInt`, `Error` instance not pre-toJSON'd), the
|
|
6694
|
+
* payload falls back to `{code, message}` only rather than crashing
|
|
6695
|
+
* the MCP/CLI wrapper when it serializes this error onto the wire.
|
|
6696
|
+
*/
|
|
6697
|
+
toJSON() {
|
|
6698
|
+
const out = { code: this.code, message: this.message };
|
|
6699
|
+
if (this.details !== void 0) {
|
|
6700
|
+
const safe = safeDetails(this.details);
|
|
6701
|
+
if (safe !== void 0) out.details = safe;
|
|
6702
|
+
}
|
|
6703
|
+
return out;
|
|
6704
|
+
}
|
|
6705
|
+
};
|
|
6706
|
+
function safeDetails(details) {
|
|
6707
|
+
try {
|
|
6708
|
+
return JSON.parse(JSON.stringify(details));
|
|
6709
|
+
} catch {
|
|
6710
|
+
return void 0;
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
function asSurfaceError(err, fallbackCode = "internal-error") {
|
|
6714
|
+
if (err instanceof SurfaceError) return err;
|
|
6715
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6716
|
+
return new SurfaceError(fallbackCode, message);
|
|
6717
|
+
}
|
|
6718
|
+
|
|
6719
|
+
// src/patterns/surface/create.ts
|
|
6720
|
+
function createGraph(spec, opts) {
|
|
6721
|
+
const structural = validateSpec(spec);
|
|
6722
|
+
if (!structural.valid) {
|
|
6723
|
+
throw new SurfaceError(
|
|
6724
|
+
"invalid-spec",
|
|
6725
|
+
`GraphSpec validation failed:
|
|
6726
|
+
${structural.errors.join("\n")}`,
|
|
6727
|
+
{ errors: structural.errors }
|
|
6728
|
+
);
|
|
6729
|
+
}
|
|
6730
|
+
const catalog = opts?.catalog ?? {};
|
|
6731
|
+
const catalogValidation = validateSpecAgainstCatalog(spec, catalog);
|
|
6732
|
+
if (!catalogValidation.valid) {
|
|
6733
|
+
throw new SurfaceError(
|
|
6734
|
+
"catalog-error",
|
|
6735
|
+
`Catalog validation failed:
|
|
6736
|
+
${catalogValidation.errors.join("\n")}`,
|
|
6737
|
+
{ errors: catalogValidation.errors }
|
|
6738
|
+
);
|
|
6739
|
+
}
|
|
6740
|
+
try {
|
|
6741
|
+
return compileSpec(spec, opts);
|
|
6742
|
+
} catch (err) {
|
|
6743
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6744
|
+
throw new SurfaceError("catalog-error", message);
|
|
6745
|
+
}
|
|
6746
|
+
}
|
|
6747
|
+
|
|
6748
|
+
// src/patterns/surface/reduce.ts
|
|
6749
|
+
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
6750
|
+
async function runReduction(spec, input, opts) {
|
|
6751
|
+
const inputPath = opts?.inputPath ?? "input";
|
|
6752
|
+
const outputPath = opts?.outputPath ?? "output";
|
|
6753
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
6754
|
+
const graph = createGraph(spec, { catalog: opts?.catalog });
|
|
6755
|
+
let outputNode;
|
|
6756
|
+
try {
|
|
6757
|
+
outputNode = graph.resolve(outputPath);
|
|
6758
|
+
} catch {
|
|
6759
|
+
graph.destroy();
|
|
6760
|
+
throw new SurfaceError(
|
|
6761
|
+
"node-not-found",
|
|
6762
|
+
`reduce: output path "${outputPath}" is not registered`,
|
|
6763
|
+
{ path: outputPath }
|
|
6764
|
+
);
|
|
6765
|
+
}
|
|
6766
|
+
try {
|
|
6767
|
+
graph.resolve(inputPath);
|
|
6768
|
+
} catch {
|
|
6769
|
+
graph.destroy();
|
|
6770
|
+
throw new SurfaceError(
|
|
6771
|
+
"node-not-found",
|
|
6772
|
+
`reduce: input path "${inputPath}" is not registered`,
|
|
6773
|
+
{ path: inputPath }
|
|
6774
|
+
);
|
|
6775
|
+
}
|
|
6776
|
+
try {
|
|
6777
|
+
return await new Promise((resolve, reject) => {
|
|
6778
|
+
let primed = false;
|
|
6779
|
+
let settled = false;
|
|
6780
|
+
let timer;
|
|
6781
|
+
let unsub;
|
|
6782
|
+
let shouldUnsub = false;
|
|
6783
|
+
const finish = (action) => {
|
|
6784
|
+
if (settled) return;
|
|
6785
|
+
settled = true;
|
|
6786
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
6787
|
+
if (unsub !== void 0) {
|
|
6788
|
+
unsub();
|
|
6789
|
+
unsub = void 0;
|
|
6790
|
+
} else {
|
|
6791
|
+
shouldUnsub = true;
|
|
6792
|
+
}
|
|
6793
|
+
action();
|
|
6794
|
+
};
|
|
6795
|
+
unsub = outputNode.subscribe((msgs) => {
|
|
6796
|
+
for (const m of msgs) {
|
|
6797
|
+
if (settled) return;
|
|
6798
|
+
if (!primed) continue;
|
|
6799
|
+
if (m[0] === DATA) {
|
|
6800
|
+
finish(() => resolve(m[1]));
|
|
6801
|
+
return;
|
|
6802
|
+
}
|
|
6803
|
+
if (m[0] === RESOLVED) {
|
|
6804
|
+
const cached2 = outputNode.cache;
|
|
6805
|
+
finish(() => resolve(cached2));
|
|
6806
|
+
return;
|
|
6807
|
+
}
|
|
6808
|
+
if (m[0] === ERROR) {
|
|
6809
|
+
const payload = m[1];
|
|
6810
|
+
const message = payload instanceof Error ? payload.message : String(payload);
|
|
6811
|
+
const cause = payload instanceof Error ? payload : void 0;
|
|
6812
|
+
finish(
|
|
6813
|
+
() => reject(
|
|
6814
|
+
new SurfaceError(
|
|
6815
|
+
"internal-error",
|
|
6816
|
+
`reduce: output emitted ERROR: ${message}`,
|
|
6817
|
+
cause != null ? { cause } : void 0
|
|
6818
|
+
)
|
|
6819
|
+
)
|
|
6820
|
+
);
|
|
6821
|
+
return;
|
|
6822
|
+
}
|
|
6823
|
+
if (m[0] === COMPLETE) {
|
|
6824
|
+
finish(
|
|
6825
|
+
() => reject(
|
|
6826
|
+
new SurfaceError(
|
|
6827
|
+
"internal-error",
|
|
6828
|
+
`reduce: output COMPLETEd without a post-push DATA`
|
|
6829
|
+
)
|
|
6830
|
+
)
|
|
6831
|
+
);
|
|
6832
|
+
return;
|
|
6833
|
+
}
|
|
6834
|
+
}
|
|
6835
|
+
});
|
|
6836
|
+
if (shouldUnsub) {
|
|
6837
|
+
unsub?.();
|
|
6838
|
+
unsub = void 0;
|
|
6839
|
+
}
|
|
6840
|
+
primed = true;
|
|
6841
|
+
try {
|
|
6842
|
+
graph.set(inputPath, input);
|
|
6843
|
+
} catch (err) {
|
|
6844
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6845
|
+
const cause = err instanceof Error ? err : void 0;
|
|
6846
|
+
finish(
|
|
6847
|
+
() => reject(
|
|
6848
|
+
new SurfaceError(
|
|
6849
|
+
"internal-error",
|
|
6850
|
+
`reduce: failed to set input on "${inputPath}": ${message}`,
|
|
6851
|
+
cause != null ? { path: inputPath, cause } : { path: inputPath }
|
|
6852
|
+
)
|
|
6853
|
+
)
|
|
6854
|
+
);
|
|
6855
|
+
return;
|
|
6856
|
+
}
|
|
6857
|
+
if (!settled && Number.isFinite(timeoutMs) && timeoutMs > 0) {
|
|
6858
|
+
timer = setTimeout(() => {
|
|
6859
|
+
finish(
|
|
6860
|
+
() => reject(
|
|
6861
|
+
new SurfaceError(
|
|
6862
|
+
"reduce-timeout",
|
|
6863
|
+
`reduce: no output emitted within ${timeoutMs}ms`,
|
|
6864
|
+
{ timeoutMs, outputPath }
|
|
6865
|
+
)
|
|
6866
|
+
)
|
|
6867
|
+
);
|
|
6868
|
+
}, timeoutMs);
|
|
6869
|
+
timer.unref?.();
|
|
6870
|
+
}
|
|
6871
|
+
});
|
|
6872
|
+
} finally {
|
|
6873
|
+
graph.destroy();
|
|
6874
|
+
}
|
|
6875
|
+
}
|
|
6876
|
+
|
|
6877
|
+
// src/patterns/surface/snapshot.ts
|
|
6878
|
+
var SNAPSHOT_WIRE_VERSION = SNAPSHOT_VERSION;
|
|
6879
|
+
function unwrapCheckpoint(raw, snapshotId) {
|
|
6880
|
+
if (raw == null || typeof raw !== "object") {
|
|
6881
|
+
throw new SurfaceError("snapshot-not-found", `snapshot "${snapshotId}" not found in tier`, {
|
|
6882
|
+
snapshotId
|
|
6883
|
+
});
|
|
6884
|
+
}
|
|
6885
|
+
const record = raw;
|
|
6886
|
+
if ("mode" in record) {
|
|
6887
|
+
if (record.mode === "full" && "snapshot" in record) {
|
|
6888
|
+
return record.snapshot;
|
|
6889
|
+
}
|
|
6890
|
+
if (record.mode === "diff") {
|
|
6891
|
+
throw new SurfaceError(
|
|
6892
|
+
"restore-failed",
|
|
6893
|
+
`snapshot "${snapshotId}" is a diff record; restore the baseline and replay WAL instead`,
|
|
6894
|
+
{ snapshotId, mode: "diff" }
|
|
6895
|
+
);
|
|
6896
|
+
}
|
|
6897
|
+
throw new SurfaceError(
|
|
6898
|
+
"restore-failed",
|
|
6899
|
+
`snapshot "${snapshotId}" has unknown mode "${String(record.mode)}"`,
|
|
6900
|
+
{ snapshotId, mode: String(record.mode) }
|
|
6901
|
+
);
|
|
6902
|
+
}
|
|
6903
|
+
if ("nodes" in record && "edges" in record && "subgraphs" in record && "name" in record) {
|
|
6904
|
+
return record;
|
|
6905
|
+
}
|
|
6906
|
+
throw new SurfaceError(
|
|
6907
|
+
"restore-failed",
|
|
6908
|
+
`snapshot "${snapshotId}" payload is not a GraphCheckpointRecord or GraphPersistSnapshot`,
|
|
6909
|
+
{ snapshotId }
|
|
6910
|
+
);
|
|
6911
|
+
}
|
|
6912
|
+
async function saveSnapshot(graph, snapshotId, tier) {
|
|
6913
|
+
let snapshot;
|
|
6914
|
+
try {
|
|
6915
|
+
snapshot = graph.snapshot();
|
|
6916
|
+
} catch (err) {
|
|
6917
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6918
|
+
throw new SurfaceError(
|
|
6919
|
+
"snapshot-failed",
|
|
6920
|
+
`snapshot "${snapshotId}" serialization failed: ${message}`,
|
|
6921
|
+
{ snapshotId }
|
|
6922
|
+
);
|
|
6923
|
+
}
|
|
6924
|
+
const record = {
|
|
6925
|
+
mode: "full",
|
|
6926
|
+
seq: 0,
|
|
6927
|
+
timestamp_ns: wallClockNs(),
|
|
6928
|
+
format_version: SNAPSHOT_WIRE_VERSION,
|
|
6929
|
+
snapshot
|
|
6930
|
+
};
|
|
6931
|
+
try {
|
|
6932
|
+
await tier.save(snapshotId, record);
|
|
6933
|
+
} catch (err) {
|
|
6934
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6935
|
+
throw new SurfaceError("snapshot-failed", `snapshot "${snapshotId}" save failed: ${message}`, {
|
|
6936
|
+
snapshotId
|
|
6937
|
+
});
|
|
6938
|
+
}
|
|
6939
|
+
return { snapshotId, timestamp_ns: record.timestamp_ns };
|
|
6940
|
+
}
|
|
6941
|
+
async function restoreSnapshot(snapshotId, tier, opts) {
|
|
6942
|
+
const raw = await tier.load(snapshotId);
|
|
6943
|
+
const snapshot = unwrapCheckpoint(raw, snapshotId);
|
|
6944
|
+
try {
|
|
6945
|
+
return Graph.fromSnapshot(
|
|
6946
|
+
snapshot,
|
|
6947
|
+
opts?.factories ? { factories: opts.factories } : void 0
|
|
6948
|
+
);
|
|
6949
|
+
} catch (err) {
|
|
6950
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6951
|
+
throw new SurfaceError(
|
|
6952
|
+
"restore-failed",
|
|
6953
|
+
`snapshot "${snapshotId}" restore failed: ${message}`,
|
|
6954
|
+
{
|
|
6955
|
+
snapshotId
|
|
6956
|
+
}
|
|
6957
|
+
);
|
|
6958
|
+
}
|
|
6959
|
+
}
|
|
6960
|
+
async function diffSnapshots(snapshotIdA, snapshotIdB, tier) {
|
|
6961
|
+
const [rawA, rawB] = await Promise.all([tier.load(snapshotIdA), tier.load(snapshotIdB)]);
|
|
6962
|
+
const snapshotA = unwrapCheckpoint(rawA, snapshotIdA);
|
|
6963
|
+
const snapshotB = unwrapCheckpoint(rawB, snapshotIdB);
|
|
6964
|
+
return Graph.diff(snapshotA, snapshotB);
|
|
6965
|
+
}
|
|
6966
|
+
async function listSnapshots(tier) {
|
|
6967
|
+
if (typeof tier.list !== "function") {
|
|
6968
|
+
throw new SurfaceError(
|
|
6969
|
+
"tier-no-list",
|
|
6970
|
+
"StorageTier does not implement list(); wrap the tier with an enumerator or use a different backend"
|
|
6971
|
+
);
|
|
6972
|
+
}
|
|
6973
|
+
return tier.list();
|
|
6974
|
+
}
|
|
6975
|
+
async function deleteSnapshot(snapshotId, tier) {
|
|
6976
|
+
if (typeof tier.clear !== "function") {
|
|
6977
|
+
throw new SurfaceError(
|
|
6978
|
+
"snapshot-failed",
|
|
6979
|
+
`StorageTier is append-only (no clear()); cannot delete "${snapshotId}"`,
|
|
6980
|
+
{ snapshotId }
|
|
6981
|
+
);
|
|
6982
|
+
}
|
|
6983
|
+
try {
|
|
6984
|
+
await tier.clear(snapshotId);
|
|
6985
|
+
} catch (err) {
|
|
6986
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6987
|
+
throw new SurfaceError(
|
|
6988
|
+
"snapshot-failed",
|
|
6989
|
+
`snapshot "${snapshotId}" delete failed: ${message}`,
|
|
6990
|
+
{
|
|
6991
|
+
snapshotId
|
|
6992
|
+
}
|
|
6993
|
+
);
|
|
6994
|
+
}
|
|
6995
|
+
}
|
|
6996
|
+
|
|
6985
6997
|
// src/index.ts
|
|
6986
6998
|
var version = "0.0.0";
|
|
6987
6999
|
export {
|
|
@@ -7021,15 +7033,20 @@ export {
|
|
|
7021
7033
|
ResettableTimer,
|
|
7022
7034
|
OVERHEAD as SIZEOF_OVERHEAD,
|
|
7023
7035
|
SIZEOF_SYMBOL,
|
|
7036
|
+
SNAPSHOT_VERSION,
|
|
7037
|
+
SNAPSHOT_WIRE_VERSION,
|
|
7024
7038
|
START,
|
|
7025
7039
|
START_MSG,
|
|
7040
|
+
SurfaceError,
|
|
7026
7041
|
TEARDOWN,
|
|
7027
7042
|
TEARDOWN_MSG,
|
|
7028
7043
|
TEARDOWN_ONLY_BATCH,
|
|
7029
7044
|
TimeoutError,
|
|
7030
7045
|
accessHintForGuard,
|
|
7046
|
+
audit_exports as accountability,
|
|
7031
7047
|
advanceVersion,
|
|
7032
7048
|
ai_exports as ai,
|
|
7049
|
+
asSurfaceError,
|
|
7033
7050
|
audit,
|
|
7034
7051
|
autoTrackNode,
|
|
7035
7052
|
batch,
|
|
@@ -7053,6 +7070,7 @@ export {
|
|
|
7053
7070
|
cqrs_exports as cqrs,
|
|
7054
7071
|
createDagCborCodec,
|
|
7055
7072
|
createDagCborZstdCodec,
|
|
7073
|
+
createGraph,
|
|
7056
7074
|
createTransport,
|
|
7057
7075
|
createVersioning,
|
|
7058
7076
|
createWatermarkController,
|
|
@@ -7064,11 +7082,13 @@ export {
|
|
|
7064
7082
|
defaultConfig,
|
|
7065
7083
|
defaultHash,
|
|
7066
7084
|
delay,
|
|
7085
|
+
deleteSnapshot,
|
|
7067
7086
|
demo_shell_exports as demoShell,
|
|
7068
7087
|
derived,
|
|
7069
7088
|
deserializeError,
|
|
7070
7089
|
dictStorage,
|
|
7071
7090
|
diffForWAL,
|
|
7091
|
+
diffSnapshots,
|
|
7072
7092
|
distill,
|
|
7073
7093
|
distinctUntilChanged,
|
|
7074
7094
|
domain_templates_exports as domainTemplates,
|
|
@@ -7080,6 +7100,7 @@ export {
|
|
|
7080
7100
|
encodeEnvelope,
|
|
7081
7101
|
escapeRegexChar,
|
|
7082
7102
|
exhaustMap,
|
|
7103
|
+
explainPath,
|
|
7083
7104
|
exponential,
|
|
7084
7105
|
externalBundle,
|
|
7085
7106
|
externalProducer,
|
|
@@ -7135,6 +7156,7 @@ export {
|
|
|
7135
7156
|
graph_exports as graph,
|
|
7136
7157
|
graphProfile,
|
|
7137
7158
|
graphspec_exports as graphspec,
|
|
7159
|
+
guarded_execution_exports as guarded,
|
|
7138
7160
|
harness_exports as harness,
|
|
7139
7161
|
indexedDbStorage,
|
|
7140
7162
|
interval,
|
|
@@ -7144,7 +7166,9 @@ export {
|
|
|
7144
7166
|
keepalive,
|
|
7145
7167
|
last,
|
|
7146
7168
|
reactive_layout_exports as layout,
|
|
7169
|
+
lens_exports as lens,
|
|
7147
7170
|
linear,
|
|
7171
|
+
listSnapshots,
|
|
7148
7172
|
lru,
|
|
7149
7173
|
map,
|
|
7150
7174
|
matchesAnyPattern,
|
|
@@ -7194,11 +7218,15 @@ export {
|
|
|
7194
7218
|
replay,
|
|
7195
7219
|
replayWAL,
|
|
7196
7220
|
rescue,
|
|
7221
|
+
resilient_pipeline_exports as resilientPipeline,
|
|
7197
7222
|
resolveBackoffPreset,
|
|
7198
7223
|
resolveDescribeFields,
|
|
7224
|
+
restoreSnapshot,
|
|
7199
7225
|
retry,
|
|
7200
7226
|
retrySource,
|
|
7227
|
+
runReduction,
|
|
7201
7228
|
sample,
|
|
7229
|
+
saveSnapshot,
|
|
7202
7230
|
scan,
|
|
7203
7231
|
serializeError,
|
|
7204
7232
|
share,
|
|
@@ -7210,6 +7238,7 @@ export {
|
|
|
7210
7238
|
solid_exports as solid,
|
|
7211
7239
|
sqliteStorage,
|
|
7212
7240
|
state,
|
|
7241
|
+
surface_exports as surface,
|
|
7213
7242
|
svelte_exports as svelte,
|
|
7214
7243
|
switchMap,
|
|
7215
7244
|
take,
|
|
@@ -7247,6 +7276,7 @@ export {
|
|
|
7247
7276
|
version,
|
|
7248
7277
|
vue_exports as vue,
|
|
7249
7278
|
wallClockNs,
|
|
7279
|
+
watchTopologyTree,
|
|
7250
7280
|
window,
|
|
7251
7281
|
windowCount,
|
|
7252
7282
|
windowTime,
|