@dxos/app-graph 0.8.3 → 0.8.4-main.f9ba587

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.
@@ -1,816 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var node_exports = {};
30
- __export(node_exports, {
31
- ACTION_GROUP_TYPE: () => ACTION_GROUP_TYPE,
32
- ACTION_TYPE: () => ACTION_TYPE,
33
- Graph: () => Graph,
34
- GraphBuilder: () => GraphBuilder,
35
- ROOT_ID: () => ROOT_ID,
36
- ROOT_TYPE: () => ROOT_TYPE,
37
- actionGroupSymbol: () => actionGroupSymbol,
38
- createExtension: () => createExtension,
39
- flattenExtensions: () => flattenExtensions,
40
- getGraph: () => getGraph,
41
- isAction: () => isAction,
42
- isActionGroup: () => isActionGroup,
43
- isActionLike: () => isActionLike,
44
- isGraphNode: () => isGraphNode,
45
- rxFromObservable: () => rxFromObservable,
46
- rxFromSignal: () => rxFromSignal
47
- });
48
- module.exports = __toCommonJS(node_exports);
49
- var import_rx_react = require("@effect-rx/rx-react");
50
- var import_effect = require("effect");
51
- var import_async = require("@dxos/async");
52
- var import_debug = require("@dxos/debug");
53
- var import_invariant = require("@dxos/invariant");
54
- var import_log = require("@dxos/log");
55
- var import_util = require("@dxos/util");
56
- var import_rx_react2 = require("@effect-rx/rx-react");
57
- var import_signals_core = require("@preact/signals-core");
58
- var import_effect2 = require("effect");
59
- var import_log2 = require("@dxos/log");
60
- var import_util2 = require("@dxos/util");
61
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
62
- var graphSymbol = Symbol("graph");
63
- var getGraph = (node) => {
64
- const graph = node[graphSymbol];
65
- (0, import_invariant.invariant)(graph, "Node is not associated with a graph.", {
66
- F: __dxlog_file,
67
- L: 25,
68
- S: void 0,
69
- A: [
70
- "graph",
71
- "'Node is not associated with a graph.'"
72
- ]
73
- });
74
- return graph;
75
- };
76
- var ROOT_ID = "root";
77
- var ROOT_TYPE = "dxos.org/type/GraphRoot";
78
- var ACTION_TYPE = "dxos.org/type/GraphAction";
79
- var ACTION_GROUP_TYPE = "dxos.org/type/GraphActionGroup";
80
- var Graph = class {
81
- constructor({ registry, nodes, edges, onExpand, onRemoveNode } = {}) {
82
- this.onNodeChanged = new import_async.Event();
83
- this._expanded = import_effect.Record.empty();
84
- this._initialized = import_effect.Record.empty();
85
- this._initialEdges = import_effect.Record.empty();
86
- this._initialNodes = import_effect.Record.fromEntries([
87
- [
88
- ROOT_ID,
89
- this._constructNode({
90
- id: ROOT_ID,
91
- type: ROOT_TYPE,
92
- data: null,
93
- properties: {}
94
- })
95
- ]
96
- ]);
97
- this._node = import_rx_react.Rx.family((id) => {
98
- const initial = import_effect.Option.flatten(import_effect.Record.get(this._initialNodes, id));
99
- return import_rx_react.Rx.make(initial).pipe(import_rx_react.Rx.keepAlive, import_rx_react.Rx.withLabel(`graph:node:${id}`));
100
- });
101
- this._nodeOrThrow = import_rx_react.Rx.family((id) => {
102
- return import_rx_react.Rx.make((get) => {
103
- const node = get(this._node(id));
104
- (0, import_invariant.invariant)(import_effect.Option.isSome(node), `Node not available: ${id}`, {
105
- F: __dxlog_file,
106
- L: 253,
107
- S: this,
108
- A: [
109
- "Option.isSome(node)",
110
- "`Node not available: ${id}`"
111
- ]
112
- });
113
- return node.value;
114
- });
115
- });
116
- this._edges = import_rx_react.Rx.family((id) => {
117
- const initial = import_effect.Record.get(this._initialEdges, id).pipe(import_effect.Option.getOrElse(() => ({
118
- inbound: [],
119
- outbound: []
120
- })));
121
- return import_rx_react.Rx.make(initial).pipe(import_rx_react.Rx.keepAlive, import_rx_react.Rx.withLabel(`graph:edges:${id}`));
122
- });
123
- this._connections = import_rx_react.Rx.family((key) => {
124
- return import_rx_react.Rx.make((get) => {
125
- const [id, relation] = key.split("$");
126
- const edges2 = get(this._edges(id));
127
- return edges2[relation].map((id2) => get(this._node(id2))).filter(import_effect.Option.isSome).map((o) => o.value);
128
- }).pipe(import_rx_react.Rx.withLabel(`graph:connections:${key}`));
129
- });
130
- this._actions = import_rx_react.Rx.family((id) => {
131
- return import_rx_react.Rx.make((get) => {
132
- return get(this._connections(`${id}$outbound`)).filter((node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE);
133
- }).pipe(import_rx_react.Rx.withLabel(`graph:actions:${id}`));
134
- });
135
- this._json = import_rx_react.Rx.family((id) => {
136
- return import_rx_react.Rx.make((get) => {
137
- const toJSON = (node, seen = []) => {
138
- const nodes2 = get(this.connections(node.id));
139
- const obj = {
140
- id: node.id.length > 32 ? `${node.id.slice(0, 32)}...` : node.id,
141
- type: node.type
142
- };
143
- if (node.properties.label) {
144
- obj.label = node.properties.label;
145
- }
146
- if (nodes2.length) {
147
- obj.nodes = nodes2.map((n) => {
148
- const nextSeen = [
149
- ...seen,
150
- node.id
151
- ];
152
- return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
153
- }).filter(import_util.isNonNullable);
154
- }
155
- return obj;
156
- };
157
- const root = get(this.nodeOrThrow(id));
158
- return toJSON(root);
159
- }).pipe(import_rx_react.Rx.withLabel(`graph:json:${id}`));
160
- });
161
- this._registry = registry ?? import_rx_react.Registry.make();
162
- this._onExpand = onExpand;
163
- this._onRemoveNode = onRemoveNode;
164
- if (nodes) {
165
- nodes.forEach((node) => {
166
- import_effect.Record.set(this._initialNodes, node.id, this._constructNode(node));
167
- });
168
- }
169
- if (edges) {
170
- Object.entries(edges).forEach(([source, edges2]) => {
171
- import_effect.Record.set(this._initialEdges, source, edges2);
172
- });
173
- }
174
- }
175
- toJSON(id = ROOT_ID) {
176
- return this._registry.get(this._json(id));
177
- }
178
- json(id = ROOT_ID) {
179
- return this._json(id);
180
- }
181
- node(id) {
182
- return this._node(id);
183
- }
184
- nodeOrThrow(id) {
185
- return this._nodeOrThrow(id);
186
- }
187
- connections(id, relation = "outbound") {
188
- return this._connections(`${id}$${relation}`);
189
- }
190
- actions(id) {
191
- return this._actions(id);
192
- }
193
- edges(id) {
194
- return this._edges(id);
195
- }
196
- get root() {
197
- return this.getNodeOrThrow(ROOT_ID);
198
- }
199
- getNode(id) {
200
- return this._registry.get(this.node(id));
201
- }
202
- getNodeOrThrow(id) {
203
- return this._registry.get(this.nodeOrThrow(id));
204
- }
205
- getConnections(id, relation = "outbound") {
206
- return this._registry.get(this.connections(id, relation));
207
- }
208
- getActions(id) {
209
- return this._registry.get(this.actions(id));
210
- }
211
- getEdges(id) {
212
- return this._registry.get(this.edges(id));
213
- }
214
- // TODO(wittjosiah): On initialize to restore state from cache.
215
- // async initialize(id: string) {
216
- // const initialized = Record.get(this._initialized, id).pipe(Option.getOrElse(() => false));
217
- // log('initialize', { id, initialized });
218
- // if (!initialized) {
219
- // await this._onInitialize?.(id);
220
- // Record.set(this._initialized, id, true);
221
- // }
222
- // }
223
- expand(id, relation = "outbound") {
224
- const key = `${id}$${relation}`;
225
- const expanded = import_effect.Record.get(this._expanded, key).pipe(import_effect.Option.getOrElse(() => false));
226
- (0, import_log.log)("expand", {
227
- key,
228
- expanded
229
- }, {
230
- F: __dxlog_file,
231
- L: 395,
232
- S: this,
233
- C: (f, a) => f(...a)
234
- });
235
- if (!expanded) {
236
- this._onExpand?.(id, relation);
237
- import_effect.Record.set(this._expanded, key, true);
238
- }
239
- }
240
- addNodes(nodes) {
241
- import_rx_react.Rx.batch(() => {
242
- nodes.map((node) => this.addNode(node));
243
- });
244
- }
245
- addNode({ nodes, edges, ...nodeArg }) {
246
- const { id, type, data = null, properties = {} } = nodeArg;
247
- const nodeRx = this._node(id);
248
- const node = this._registry.get(nodeRx);
249
- import_effect.Option.match(node, {
250
- onSome: (node2) => {
251
- const typeChanged = node2.type !== type;
252
- const dataChanged = node2.data !== data;
253
- const propertiesChanged = Object.keys(properties).some((key) => node2.properties[key] !== properties[key]);
254
- (0, import_log.log)("existing node", {
255
- id,
256
- typeChanged,
257
- dataChanged,
258
- propertiesChanged
259
- }, {
260
- F: __dxlog_file,
261
- L: 417,
262
- S: this,
263
- C: (f, a) => f(...a)
264
- });
265
- if (typeChanged || dataChanged || propertiesChanged) {
266
- (0, import_log.log)("updating node", {
267
- id,
268
- type,
269
- data,
270
- properties
271
- }, {
272
- F: __dxlog_file,
273
- L: 419,
274
- S: this,
275
- C: (f, a) => f(...a)
276
- });
277
- const newNode = import_effect.Option.some({
278
- ...node2,
279
- type,
280
- data,
281
- properties: {
282
- ...node2.properties,
283
- ...properties
284
- }
285
- });
286
- this._registry.set(nodeRx, newNode);
287
- this.onNodeChanged.emit({
288
- id,
289
- node: newNode
290
- });
291
- }
292
- },
293
- onNone: () => {
294
- (0, import_log.log)("new node", {
295
- id,
296
- type,
297
- data,
298
- properties
299
- }, {
300
- F: __dxlog_file,
301
- L: 426,
302
- S: this,
303
- C: (f, a) => f(...a)
304
- });
305
- const newNode = this._constructNode({
306
- id,
307
- type,
308
- data,
309
- properties
310
- });
311
- this._registry.set(nodeRx, newNode);
312
- this.onNodeChanged.emit({
313
- id,
314
- node: newNode
315
- });
316
- }
317
- });
318
- if (nodes) {
319
- this.addNodes(nodes);
320
- const _edges = nodes.map((node2) => ({
321
- source: id,
322
- target: node2.id
323
- }));
324
- this.addEdges(_edges);
325
- }
326
- if (edges) {
327
- (0, import_debug.todo)();
328
- }
329
- }
330
- removeNodes(ids, edges = false) {
331
- import_rx_react.Rx.batch(() => {
332
- ids.map((id) => this.removeNode(id, edges));
333
- });
334
- }
335
- removeNode(id, edges = false) {
336
- const nodeRx = this._node(id);
337
- this._registry.set(nodeRx, import_effect.Option.none());
338
- this.onNodeChanged.emit({
339
- id,
340
- node: import_effect.Option.none()
341
- });
342
- if (edges) {
343
- const { inbound, outbound } = this._registry.get(this._edges(id));
344
- const edges2 = [
345
- ...inbound.map((source) => ({
346
- source,
347
- target: id
348
- })),
349
- ...outbound.map((target) => ({
350
- source: id,
351
- target
352
- }))
353
- ];
354
- this.removeEdges(edges2);
355
- }
356
- this._onRemoveNode?.(id);
357
- }
358
- addEdges(edges) {
359
- import_rx_react.Rx.batch(() => {
360
- edges.map((edge) => this.addEdge(edge));
361
- });
362
- }
363
- addEdge(edgeArg) {
364
- const sourceRx = this._edges(edgeArg.source);
365
- const source = this._registry.get(sourceRx);
366
- if (!source.outbound.includes(edgeArg.target)) {
367
- (0, import_log.log)("add outbound edge", {
368
- source: edgeArg.source,
369
- target: edgeArg.target
370
- }, {
371
- F: __dxlog_file,
372
- L: 481,
373
- S: this,
374
- C: (f, a) => f(...a)
375
- });
376
- this._registry.set(sourceRx, {
377
- inbound: source.inbound,
378
- outbound: [
379
- ...source.outbound,
380
- edgeArg.target
381
- ]
382
- });
383
- }
384
- const targetRx = this._edges(edgeArg.target);
385
- const target = this._registry.get(targetRx);
386
- if (!target.inbound.includes(edgeArg.source)) {
387
- (0, import_log.log)("add inbound edge", {
388
- source: edgeArg.source,
389
- target: edgeArg.target
390
- }, {
391
- F: __dxlog_file,
392
- L: 488,
393
- S: this,
394
- C: (f, a) => f(...a)
395
- });
396
- this._registry.set(targetRx, {
397
- inbound: [
398
- ...target.inbound,
399
- edgeArg.source
400
- ],
401
- outbound: target.outbound
402
- });
403
- }
404
- }
405
- removeEdges(edges, removeOrphans = false) {
406
- import_rx_react.Rx.batch(() => {
407
- edges.map((edge) => this.removeEdge(edge, removeOrphans));
408
- });
409
- }
410
- removeEdge(edgeArg, removeOrphans = false) {
411
- const sourceRx = this._edges(edgeArg.source);
412
- const source = this._registry.get(sourceRx);
413
- if (source.outbound.includes(edgeArg.target)) {
414
- this._registry.set(sourceRx, {
415
- inbound: source.inbound,
416
- outbound: source.outbound.filter((id) => id !== edgeArg.target)
417
- });
418
- }
419
- const targetRx = this._edges(edgeArg.target);
420
- const target = this._registry.get(targetRx);
421
- if (target.inbound.includes(edgeArg.source)) {
422
- this._registry.set(targetRx, {
423
- inbound: target.inbound.filter((id) => id !== edgeArg.source),
424
- outbound: target.outbound
425
- });
426
- }
427
- if (removeOrphans) {
428
- const source2 = this._registry.get(sourceRx);
429
- const target2 = this._registry.get(targetRx);
430
- if (source2.outbound.length === 0 && source2.inbound.length === 0 && edgeArg.source !== ROOT_ID) {
431
- this.removeNodes([
432
- edgeArg.source
433
- ]);
434
- }
435
- if (target2.outbound.length === 0 && target2.inbound.length === 0 && edgeArg.target !== ROOT_ID) {
436
- this.removeNodes([
437
- edgeArg.target
438
- ]);
439
- }
440
- }
441
- }
442
- sortEdges(id, relation, order) {
443
- const edgesRx = this._edges(id);
444
- const edges = this._registry.get(edgesRx);
445
- const unsorted = edges[relation].filter((id2) => !order.includes(id2)) ?? [];
446
- const sorted = order.filter((id2) => edges[relation].includes(id2)) ?? [];
447
- edges[relation].splice(0, edges[relation].length, ...[
448
- ...sorted,
449
- ...unsorted
450
- ]);
451
- this._registry.set(edgesRx, edges);
452
- }
453
- traverse({ visitor, source = ROOT_ID, relation = "outbound" }, path = []) {
454
- if (path.includes(source)) {
455
- return;
456
- }
457
- const node = this.getNodeOrThrow(source);
458
- const shouldContinue = visitor(node, [
459
- ...path,
460
- source
461
- ]);
462
- if (shouldContinue === false) {
463
- return;
464
- }
465
- Object.values(this.getConnections(source, relation)).forEach((child) => this.traverse({
466
- source: child.id,
467
- relation,
468
- visitor
469
- }, [
470
- ...path,
471
- source
472
- ]));
473
- }
474
- getPath({ source = "root", target }) {
475
- return (0, import_effect.pipe)(this.getNode(source), import_effect.Option.flatMap((node) => {
476
- let found = import_effect.Option.none();
477
- this.traverse({
478
- source: node.id,
479
- visitor: (node2, path) => {
480
- if (import_effect.Option.isSome(found)) {
481
- return false;
482
- }
483
- if (node2.id === target) {
484
- found = import_effect.Option.some(path);
485
- }
486
- }
487
- });
488
- return found;
489
- }));
490
- }
491
- async waitForPath(params, { timeout = 5e3, interval = 500 } = {}) {
492
- const path = this.getPath(params);
493
- if (import_effect.Option.isSome(path)) {
494
- return path.value;
495
- }
496
- const trigger = new import_async.Trigger();
497
- const i = setInterval(() => {
498
- const path2 = this.getPath(params);
499
- if (import_effect.Option.isSome(path2)) {
500
- trigger.wake(path2.value);
501
- }
502
- }, interval);
503
- return trigger.wait({
504
- timeout
505
- }).finally(() => clearInterval(i));
506
- }
507
- /** @internal */
508
- _constructNode(node) {
509
- return import_effect.Option.some({
510
- [graphSymbol]: this,
511
- data: null,
512
- properties: {},
513
- ...node
514
- });
515
- }
516
- };
517
- var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
518
- var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" : false;
519
- var actionGroupSymbol = Symbol("ActionGroup");
520
- var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol : false;
521
- var isActionLike = (data) => isAction(data) || isActionGroup(data);
522
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
523
- var createExtension = (extension) => {
524
- const { id, position = "static", relation = "outbound", connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
525
- const getId = (key) => `${id}/${key}`;
526
- const connector = _connector && import_rx_react2.Rx.family((node) => _connector(node).pipe(import_rx_react2.Rx.withLabel(`graph-builder:_connector:${id}`)));
527
- const actionGroups = _actionGroups && import_rx_react2.Rx.family((node) => _actionGroups(node).pipe(import_rx_react2.Rx.withLabel(`graph-builder:_actionGroups:${id}`)));
528
- const actions = _actions && import_rx_react2.Rx.family((node) => _actions(node).pipe(import_rx_react2.Rx.withLabel(`graph-builder:_actions:${id}`)));
529
- return [
530
- // resolver ? { id: getId('resolver'), position, resolver } : undefined,
531
- connector ? {
532
- id: getId("connector"),
533
- position,
534
- relation,
535
- connector: import_rx_react2.Rx.family((node) => import_rx_react2.Rx.make((get) => {
536
- try {
537
- return get(connector(node));
538
- } catch {
539
- import_log2.log.warn("Error in connector", {
540
- id: getId("connector"),
541
- node
542
- }, {
543
- F: __dxlog_file2,
544
- L: 101,
545
- S: void 0,
546
- C: (f, a) => f(...a)
547
- });
548
- return [];
549
- }
550
- }).pipe(import_rx_react2.Rx.withLabel(`graph-builder:connector:${id}`)))
551
- } : void 0,
552
- actionGroups ? {
553
- id: getId("actionGroups"),
554
- position,
555
- relation: "outbound",
556
- connector: import_rx_react2.Rx.family((node) => import_rx_react2.Rx.make((get) => {
557
- try {
558
- return get(actionGroups(node)).map((arg) => ({
559
- ...arg,
560
- data: actionGroupSymbol,
561
- type: ACTION_GROUP_TYPE
562
- }));
563
- } catch {
564
- import_log2.log.warn("Error in actionGroups", {
565
- id: getId("actionGroups"),
566
- node
567
- }, {
568
- F: __dxlog_file2,
569
- L: 122,
570
- S: void 0,
571
- C: (f, a) => f(...a)
572
- });
573
- return [];
574
- }
575
- }).pipe(import_rx_react2.Rx.withLabel(`graph-builder:connector:actionGroups:${id}`)))
576
- } : void 0,
577
- actions ? {
578
- id: getId("actions"),
579
- position,
580
- relation: "outbound",
581
- connector: import_rx_react2.Rx.family((node) => import_rx_react2.Rx.make((get) => {
582
- try {
583
- return get(actions(node)).map((arg) => ({
584
- ...arg,
585
- type: ACTION_TYPE
586
- }));
587
- } catch {
588
- import_log2.log.warn("Error in actions", {
589
- id: getId("actions"),
590
- node
591
- }, {
592
- F: __dxlog_file2,
593
- L: 139,
594
- S: void 0,
595
- C: (f, a) => f(...a)
596
- });
597
- return [];
598
- }
599
- }).pipe(import_rx_react2.Rx.withLabel(`graph-builder:connector:actions:${id}`)))
600
- } : void 0
601
- ].filter(import_util2.isNonNullable);
602
- };
603
- var flattenExtensions = (extension, acc = []) => {
604
- if (import_effect2.Array.isArray(extension)) {
605
- return [
606
- ...acc,
607
- ...extension.flatMap((ext) => flattenExtensions(ext, acc))
608
- ];
609
- } else {
610
- return [
611
- ...acc,
612
- extension
613
- ];
614
- }
615
- };
616
- var GraphBuilder = class _GraphBuilder {
617
- constructor({ registry, ...params } = {}) {
618
- this._connectorSubscriptions = /* @__PURE__ */ new Map();
619
- this._extensions = import_rx_react2.Rx.make(import_effect2.Record.empty()).pipe(import_rx_react2.Rx.keepAlive, import_rx_react2.Rx.withLabel("graph-builder:extensions"));
620
- this._connectors = import_rx_react2.Rx.family((key) => {
621
- return import_rx_react2.Rx.make((get) => {
622
- const [id, relation] = key.split("+");
623
- const node = this._graph.node(id);
624
- return (0, import_effect2.pipe)(
625
- get(this._extensions),
626
- import_effect2.Record.values,
627
- // TODO(wittjosiah): Sort on write rather than read.
628
- import_effect2.Array.sortBy(import_util2.byPosition),
629
- import_effect2.Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
630
- import_effect2.Array.map(({ connector }) => connector?.(node)),
631
- import_effect2.Array.filter(import_util2.isNonNullable),
632
- import_effect2.Array.flatMap((result) => get(result))
633
- );
634
- }).pipe(import_rx_react2.Rx.withLabel(`graph-builder:connectors:${key}`));
635
- });
636
- this._registry = registry ?? import_rx_react2.Registry.make();
637
- this._graph = new Graph({
638
- ...params,
639
- registry: this._registry,
640
- onExpand: (id, relation) => this._onExpand(id, relation),
641
- // onInitialize: (id) => this._onInitialize(id),
642
- onRemoveNode: (id) => this._onRemoveNode(id)
643
- });
644
- }
645
- static from(pickle, registry) {
646
- if (!pickle) {
647
- return new _GraphBuilder({
648
- registry
649
- });
650
- }
651
- const { nodes, edges } = JSON.parse(pickle);
652
- return new _GraphBuilder({
653
- nodes,
654
- edges,
655
- registry
656
- });
657
- }
658
- get graph() {
659
- return this._graph;
660
- }
661
- get extensions() {
662
- return this._extensions;
663
- }
664
- addExtension(extensions) {
665
- flattenExtensions(extensions).forEach((extension) => {
666
- const extensions2 = this._registry.get(this._extensions);
667
- this._registry.set(this._extensions, import_effect2.Record.set(extensions2, extension.id, extension));
668
- });
669
- return this;
670
- }
671
- removeExtension(id) {
672
- const extensions = this._registry.get(this._extensions);
673
- this._registry.set(this._extensions, import_effect2.Record.remove(extensions, id));
674
- return this;
675
- }
676
- async explore({ registry = import_rx_react2.Registry.make(), source = ROOT_ID, relation = "outbound", visitor }, path = []) {
677
- if (path.includes(source)) {
678
- return;
679
- }
680
- if (!(0, import_util2.isNode)()) {
681
- const { yieldOrContinue } = await import("main-thread-scheduling");
682
- await yieldOrContinue("idle");
683
- }
684
- const node = registry.get(this._graph.nodeOrThrow(source));
685
- const shouldContinue = await visitor(node, [
686
- ...path,
687
- node.id
688
- ]);
689
- if (shouldContinue === false) {
690
- return;
691
- }
692
- const nodes = Object.values(this._registry.get(this._extensions)).filter((extension) => relation === (extension.relation ?? "outbound")).map((extension) => extension.connector).filter(import_util2.isNonNullable).flatMap((connector) => registry.get(connector(this._graph.node(source))));
693
- await Promise.all(nodes.map((nodeArg) => {
694
- registry.set(this._graph._node(nodeArg.id), this._graph._constructNode(nodeArg));
695
- return this.explore({
696
- registry,
697
- source: nodeArg.id,
698
- relation,
699
- visitor
700
- }, [
701
- ...path,
702
- node.id
703
- ]);
704
- }));
705
- if (registry !== this._registry) {
706
- registry.reset();
707
- registry.dispose();
708
- }
709
- }
710
- destroy() {
711
- this._connectorSubscriptions.forEach((unsubscribe) => unsubscribe());
712
- this._connectorSubscriptions.clear();
713
- }
714
- _onExpand(id, relation) {
715
- (0, import_log2.log)("onExpand", {
716
- id,
717
- relation,
718
- registry: (0, import_util2.getDebugName)(this._registry)
719
- }, {
720
- F: __dxlog_file2,
721
- L: 301,
722
- S: this,
723
- C: (f, a) => f(...a)
724
- });
725
- const connectors = this._connectors(`${id}+${relation}`);
726
- let previous = [];
727
- const cancel = this._registry.subscribe(connectors, (nodes) => {
728
- const ids = nodes.map((n) => n.id);
729
- const removed = previous.filter((id2) => !ids.includes(id2));
730
- previous = ids;
731
- (0, import_log2.log)("update", {
732
- id,
733
- relation,
734
- ids,
735
- removed
736
- }, {
737
- F: __dxlog_file2,
738
- L: 312,
739
- S: this,
740
- C: (f, a) => f(...a)
741
- });
742
- const update = () => {
743
- import_rx_react2.Rx.batch(() => {
744
- this._graph.removeEdges(removed.map((target) => ({
745
- source: id,
746
- target
747
- })), true);
748
- this._graph.addNodes(nodes);
749
- this._graph.addEdges(nodes.map((node) => relation === "outbound" ? {
750
- source: id,
751
- target: node.id
752
- } : {
753
- source: node.id,
754
- target: id
755
- }));
756
- this._graph.sortEdges(id, relation, nodes.map(({ id: id2 }) => id2));
757
- });
758
- };
759
- if (typeof requestAnimationFrame === "function") {
760
- requestAnimationFrame(update);
761
- } else {
762
- update();
763
- }
764
- }, {
765
- immediate: true
766
- });
767
- this._connectorSubscriptions.set(id, cancel);
768
- }
769
- // TODO(wittjosiah): On initialize to restore state from cache.
770
- // private async _onInitialize(id: string) {
771
- // log('onInitialize', { id });
772
- // }
773
- _onRemoveNode(id) {
774
- this._connectorSubscriptions.get(id)?.();
775
- this._connectorSubscriptions.delete(id);
776
- }
777
- };
778
- var rxFromSignal = (cb) => {
779
- return import_rx_react2.Rx.make((get) => {
780
- const dispose = (0, import_signals_core.effect)(() => {
781
- get.setSelf(cb());
782
- });
783
- get.addFinalizer(() => dispose());
784
- return cb();
785
- });
786
- };
787
- var observableFamily = import_rx_react2.Rx.family((observable) => {
788
- return import_rx_react2.Rx.make((get) => {
789
- const subscription = observable.subscribe((value) => get.setSelf(value));
790
- get.addFinalizer(() => subscription.unsubscribe());
791
- return observable.get();
792
- });
793
- });
794
- var rxFromObservable = (observable) => {
795
- return observableFamily(observable);
796
- };
797
- // Annotate the CommonJS export names for ESM import in node:
798
- 0 && (module.exports = {
799
- ACTION_GROUP_TYPE,
800
- ACTION_TYPE,
801
- Graph,
802
- GraphBuilder,
803
- ROOT_ID,
804
- ROOT_TYPE,
805
- actionGroupSymbol,
806
- createExtension,
807
- flattenExtensions,
808
- getGraph,
809
- isAction,
810
- isActionGroup,
811
- isActionLike,
812
- isGraphNode,
813
- rxFromObservable,
814
- rxFromSignal
815
- });
816
- //# sourceMappingURL=index.cjs.map