@dxos/app-graph 0.8.4-main.84f28bd → 0.8.4-main.ae835ea
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +207 -149
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +207 -149
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/graph-builder.d.ts +15 -4
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +7 -3
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +1 -1
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts +8 -10
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +1 -1
- package/dist/types/src/testing.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +31 -33
- package/src/graph-builder.test.ts +67 -9
- package/src/graph-builder.ts +69 -22
- package/src/graph.test.ts +2 -2
- package/src/graph.ts +20 -19
- package/src/node.ts +5 -3
- package/src/signals-integration.test.ts +7 -7
- package/src/stories/EchoGraph.stories.tsx +29 -26
- package/src/testing.ts +1 -1
|
@@ -2,7 +2,9 @@ import { createRequire } from 'node:module';const require = createRequire(import
|
|
|
2
2
|
|
|
3
3
|
// src/graph.ts
|
|
4
4
|
import { Registry, Rx } from "@effect-rx/rx-react";
|
|
5
|
-
import
|
|
5
|
+
import * as Function from "effect/Function";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Record from "effect/Record";
|
|
6
8
|
import { Event, Trigger } from "@dxos/async";
|
|
7
9
|
import { todo } from "@dxos/debug";
|
|
8
10
|
import { invariant } from "@dxos/invariant";
|
|
@@ -14,7 +16,7 @@ var getGraph = (node) => {
|
|
|
14
16
|
const graph = node[graphSymbol];
|
|
15
17
|
invariant(graph, "Node is not associated with a graph.", {
|
|
16
18
|
F: __dxlog_file,
|
|
17
|
-
L:
|
|
19
|
+
L: 27,
|
|
18
20
|
S: void 0,
|
|
19
21
|
A: [
|
|
20
22
|
"graph",
|
|
@@ -28,90 +30,95 @@ var ROOT_TYPE = "dxos.org/type/GraphRoot";
|
|
|
28
30
|
var ACTION_TYPE = "dxos.org/type/GraphAction";
|
|
29
31
|
var ACTION_GROUP_TYPE = "dxos.org/type/GraphActionGroup";
|
|
30
32
|
var Graph = class {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
33
|
+
onNodeChanged = new Event();
|
|
34
|
+
_onExpand;
|
|
35
|
+
_onInitialize;
|
|
36
|
+
_onRemoveNode;
|
|
37
|
+
_registry;
|
|
38
|
+
_expanded = Record.empty();
|
|
39
|
+
_initialized = Record.empty();
|
|
40
|
+
_initialEdges = Record.empty();
|
|
41
|
+
_initialNodes = Record.fromEntries([
|
|
42
|
+
[
|
|
43
|
+
ROOT_ID,
|
|
44
|
+
this._constructNode({
|
|
45
|
+
id: ROOT_ID,
|
|
46
|
+
type: ROOT_TYPE,
|
|
47
|
+
data: null,
|
|
48
|
+
properties: {}
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
]);
|
|
52
|
+
/** @internal */
|
|
53
|
+
_node = Rx.family((id) => {
|
|
54
|
+
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
55
|
+
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:node:${id}`));
|
|
56
|
+
});
|
|
57
|
+
_nodeOrThrow = Rx.family((id) => {
|
|
58
|
+
return Rx.make((get2) => {
|
|
59
|
+
const node = get2(this._node(id));
|
|
60
|
+
invariant(Option.isSome(node), `Node not available: ${id}`, {
|
|
61
|
+
F: __dxlog_file,
|
|
62
|
+
L: 254,
|
|
63
|
+
S: this,
|
|
64
|
+
A: [
|
|
65
|
+
"Option.isSome(node)",
|
|
66
|
+
"`Node not available: ${id}`"
|
|
67
|
+
]
|
|
65
68
|
});
|
|
69
|
+
return node.value;
|
|
66
70
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (node.properties.label) {
|
|
97
|
-
obj.label = node.properties.label;
|
|
98
|
-
}
|
|
99
|
-
if (nodes.length) {
|
|
100
|
-
obj.nodes = nodes.map((n) => {
|
|
101
|
-
const nextSeen = [
|
|
102
|
-
...seen,
|
|
103
|
-
node.id
|
|
104
|
-
];
|
|
105
|
-
return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
|
|
106
|
-
}).filter(isNonNullable);
|
|
107
|
-
}
|
|
108
|
-
return obj;
|
|
71
|
+
});
|
|
72
|
+
_edges = Rx.family((id) => {
|
|
73
|
+
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
74
|
+
inbound: [],
|
|
75
|
+
outbound: []
|
|
76
|
+
})));
|
|
77
|
+
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:edges:${id}`));
|
|
78
|
+
});
|
|
79
|
+
// NOTE: Currently the argument to the family needs to be referentially stable for the rx to be referentially stable.
|
|
80
|
+
// TODO(wittjosiah): Rx feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
81
|
+
_connections = Rx.family((key) => {
|
|
82
|
+
return Rx.make((get2) => {
|
|
83
|
+
const [id, relation] = key.split("$");
|
|
84
|
+
const edges = get2(this._edges(id));
|
|
85
|
+
return edges[relation].map((id2) => get2(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
86
|
+
}).pipe(Rx.withLabel(`graph:connections:${key}`));
|
|
87
|
+
});
|
|
88
|
+
_actions = Rx.family((id) => {
|
|
89
|
+
return Rx.make((get2) => {
|
|
90
|
+
return get2(this._connections(`${id}$outbound`)).filter((node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE);
|
|
91
|
+
}).pipe(Rx.withLabel(`graph:actions:${id}`));
|
|
92
|
+
});
|
|
93
|
+
_json = Rx.family((id) => {
|
|
94
|
+
return Rx.make((get2) => {
|
|
95
|
+
const toJSON = (node, seen = []) => {
|
|
96
|
+
const nodes = get2(this.connections(node.id));
|
|
97
|
+
const obj = {
|
|
98
|
+
id: node.id,
|
|
99
|
+
type: node.type
|
|
109
100
|
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
if (node.properties.label) {
|
|
102
|
+
obj.label = node.properties.label;
|
|
103
|
+
}
|
|
104
|
+
if (nodes.length) {
|
|
105
|
+
obj.nodes = nodes.map((n) => {
|
|
106
|
+
const nextSeen = [
|
|
107
|
+
...seen,
|
|
108
|
+
node.id
|
|
109
|
+
];
|
|
110
|
+
return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
|
|
111
|
+
}).filter(isNonNullable);
|
|
112
|
+
}
|
|
113
|
+
return obj;
|
|
114
|
+
};
|
|
115
|
+
const root = get2(this.nodeOrThrow(id));
|
|
116
|
+
return toJSON(root);
|
|
117
|
+
}).pipe(Rx.withLabel(`graph:json:${id}`));
|
|
118
|
+
});
|
|
119
|
+
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
114
120
|
this._registry = registry ?? Registry.make();
|
|
121
|
+
this._onInitialize = onInitialize;
|
|
115
122
|
this._onExpand = onExpand;
|
|
116
123
|
this._onRemoveNode = onRemoveNode;
|
|
117
124
|
if (nodes) {
|
|
@@ -164,15 +171,22 @@ var Graph = class {
|
|
|
164
171
|
getEdges(id) {
|
|
165
172
|
return this._registry.get(this.edges(id));
|
|
166
173
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
async initialize(id) {
|
|
175
|
+
const initialized = Record.get(this._initialized, id).pipe(Option.getOrElse(() => false));
|
|
176
|
+
log("initialize", {
|
|
177
|
+
id,
|
|
178
|
+
initialized
|
|
179
|
+
}, {
|
|
180
|
+
F: __dxlog_file,
|
|
181
|
+
L: 386,
|
|
182
|
+
S: this,
|
|
183
|
+
C: (f, a) => f(...a)
|
|
184
|
+
});
|
|
185
|
+
if (!initialized) {
|
|
186
|
+
await this._onInitialize?.(id);
|
|
187
|
+
Record.set(this._initialized, id, true);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
176
190
|
expand(id, relation = "outbound") {
|
|
177
191
|
const key = `${id}$${relation}`;
|
|
178
192
|
const expanded = Record.get(this._expanded, key).pipe(Option.getOrElse(() => false));
|
|
@@ -181,7 +195,7 @@ var Graph = class {
|
|
|
181
195
|
expanded
|
|
182
196
|
}, {
|
|
183
197
|
F: __dxlog_file,
|
|
184
|
-
L:
|
|
198
|
+
L: 396,
|
|
185
199
|
S: this,
|
|
186
200
|
C: (f, a) => f(...a)
|
|
187
201
|
});
|
|
@@ -211,7 +225,7 @@ var Graph = class {
|
|
|
211
225
|
propertiesChanged
|
|
212
226
|
}, {
|
|
213
227
|
F: __dxlog_file,
|
|
214
|
-
L:
|
|
228
|
+
L: 418,
|
|
215
229
|
S: this,
|
|
216
230
|
C: (f, a) => f(...a)
|
|
217
231
|
});
|
|
@@ -223,7 +237,7 @@ var Graph = class {
|
|
|
223
237
|
properties
|
|
224
238
|
}, {
|
|
225
239
|
F: __dxlog_file,
|
|
226
|
-
L:
|
|
240
|
+
L: 420,
|
|
227
241
|
S: this,
|
|
228
242
|
C: (f, a) => f(...a)
|
|
229
243
|
});
|
|
@@ -251,7 +265,7 @@ var Graph = class {
|
|
|
251
265
|
properties
|
|
252
266
|
}, {
|
|
253
267
|
F: __dxlog_file,
|
|
254
|
-
L:
|
|
268
|
+
L: 427,
|
|
255
269
|
S: this,
|
|
256
270
|
C: (f, a) => f(...a)
|
|
257
271
|
});
|
|
@@ -322,7 +336,7 @@ var Graph = class {
|
|
|
322
336
|
target: edgeArg.target
|
|
323
337
|
}, {
|
|
324
338
|
F: __dxlog_file,
|
|
325
|
-
L:
|
|
339
|
+
L: 482,
|
|
326
340
|
S: this,
|
|
327
341
|
C: (f, a) => f(...a)
|
|
328
342
|
});
|
|
@@ -342,7 +356,7 @@ var Graph = class {
|
|
|
342
356
|
target: edgeArg.target
|
|
343
357
|
}, {
|
|
344
358
|
F: __dxlog_file,
|
|
345
|
-
L:
|
|
359
|
+
L: 489,
|
|
346
360
|
S: this,
|
|
347
361
|
C: (f, a) => f(...a)
|
|
348
362
|
});
|
|
@@ -425,7 +439,7 @@ var Graph = class {
|
|
|
425
439
|
]));
|
|
426
440
|
}
|
|
427
441
|
getPath({ source = "root", target }) {
|
|
428
|
-
return pipe(this.getNode(source), Option.flatMap((node) => {
|
|
442
|
+
return Function.pipe(this.getNode(source), Option.flatMap((node) => {
|
|
429
443
|
let found = Option.none();
|
|
430
444
|
this.traverse({
|
|
431
445
|
source: node.id,
|
|
@@ -471,41 +485,49 @@ var Graph = class {
|
|
|
471
485
|
// src/graph-builder.ts
|
|
472
486
|
import { Registry as Registry2, Rx as Rx2 } from "@effect-rx/rx-react";
|
|
473
487
|
import { effect } from "@preact/signals-core";
|
|
474
|
-
import
|
|
488
|
+
import * as Array from "effect/Array";
|
|
489
|
+
import * as Function2 from "effect/Function";
|
|
490
|
+
import * as Option2 from "effect/Option";
|
|
491
|
+
import * as Record2 from "effect/Record";
|
|
475
492
|
import { log as log2 } from "@dxos/log";
|
|
476
493
|
import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
477
494
|
|
|
478
495
|
// src/node.ts
|
|
479
496
|
var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
|
|
480
|
-
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" : false;
|
|
497
|
+
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" && data.type === ACTION_TYPE : false;
|
|
481
498
|
var actionGroupSymbol = Symbol("ActionGroup");
|
|
482
|
-
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol : false;
|
|
499
|
+
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ACTION_GROUP_TYPE : false;
|
|
483
500
|
var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
484
501
|
|
|
485
502
|
// src/graph-builder.ts
|
|
486
503
|
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
487
504
|
var createExtension = (extension) => {
|
|
488
|
-
const { id, position = "static", relation = "outbound", connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
505
|
+
const { id, position = "static", relation = "outbound", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
489
506
|
const getId = (key) => `${id}/${key}`;
|
|
507
|
+
const resolver = _resolver && Rx2.family((id2) => _resolver(id2).pipe(Rx2.withLabel(`graph-builder:_resolver:${id2}`)));
|
|
490
508
|
const connector = _connector && Rx2.family((node) => _connector(node).pipe(Rx2.withLabel(`graph-builder:_connector:${id}`)));
|
|
491
509
|
const actionGroups = _actionGroups && Rx2.family((node) => _actionGroups(node).pipe(Rx2.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
492
510
|
const actions = _actions && Rx2.family((node) => _actions(node).pipe(Rx2.withLabel(`graph-builder:_actions:${id}`)));
|
|
493
511
|
return [
|
|
494
|
-
|
|
512
|
+
resolver ? {
|
|
513
|
+
id: getId("resolver"),
|
|
514
|
+
position,
|
|
515
|
+
resolver
|
|
516
|
+
} : void 0,
|
|
495
517
|
connector ? {
|
|
496
518
|
id: getId("connector"),
|
|
497
519
|
position,
|
|
498
520
|
relation,
|
|
499
|
-
connector: Rx2.family((node) => Rx2.make((
|
|
521
|
+
connector: Rx2.family((node) => Rx2.make((get2) => {
|
|
500
522
|
try {
|
|
501
|
-
return
|
|
523
|
+
return get2(connector(node));
|
|
502
524
|
} catch {
|
|
503
525
|
log2.warn("Error in connector", {
|
|
504
526
|
id: getId("connector"),
|
|
505
527
|
node
|
|
506
528
|
}, {
|
|
507
529
|
F: __dxlog_file2,
|
|
508
|
-
L:
|
|
530
|
+
L: 112,
|
|
509
531
|
S: void 0,
|
|
510
532
|
C: (f, a) => f(...a)
|
|
511
533
|
});
|
|
@@ -517,9 +539,9 @@ var createExtension = (extension) => {
|
|
|
517
539
|
id: getId("actionGroups"),
|
|
518
540
|
position,
|
|
519
541
|
relation: "outbound",
|
|
520
|
-
connector: Rx2.family((node) => Rx2.make((
|
|
542
|
+
connector: Rx2.family((node) => Rx2.make((get2) => {
|
|
521
543
|
try {
|
|
522
|
-
return
|
|
544
|
+
return get2(actionGroups(node)).map((arg) => ({
|
|
523
545
|
...arg,
|
|
524
546
|
data: actionGroupSymbol,
|
|
525
547
|
type: ACTION_GROUP_TYPE
|
|
@@ -530,7 +552,7 @@ var createExtension = (extension) => {
|
|
|
530
552
|
node
|
|
531
553
|
}, {
|
|
532
554
|
F: __dxlog_file2,
|
|
533
|
-
L:
|
|
555
|
+
L: 133,
|
|
534
556
|
S: void 0,
|
|
535
557
|
C: (f, a) => f(...a)
|
|
536
558
|
});
|
|
@@ -542,9 +564,9 @@ var createExtension = (extension) => {
|
|
|
542
564
|
id: getId("actions"),
|
|
543
565
|
position,
|
|
544
566
|
relation: "outbound",
|
|
545
|
-
connector: Rx2.family((node) => Rx2.make((
|
|
567
|
+
connector: Rx2.family((node) => Rx2.make((get2) => {
|
|
546
568
|
try {
|
|
547
|
-
return
|
|
569
|
+
return get2(actions(node)).map((arg) => ({
|
|
548
570
|
...arg,
|
|
549
571
|
type: ACTION_TYPE
|
|
550
572
|
}));
|
|
@@ -554,7 +576,7 @@ var createExtension = (extension) => {
|
|
|
554
576
|
node
|
|
555
577
|
}, {
|
|
556
578
|
F: __dxlog_file2,
|
|
557
|
-
L:
|
|
579
|
+
L: 150,
|
|
558
580
|
S: void 0,
|
|
559
581
|
C: (f, a) => f(...a)
|
|
560
582
|
});
|
|
@@ -578,32 +600,19 @@ var flattenExtensions = (extension, acc = []) => {
|
|
|
578
600
|
}
|
|
579
601
|
};
|
|
580
602
|
var GraphBuilder = class _GraphBuilder {
|
|
603
|
+
// TODO(wittjosiah): Use Context.
|
|
604
|
+
_subscriptions = /* @__PURE__ */ new Map();
|
|
605
|
+
_extensions = Rx2.make(Record2.empty()).pipe(Rx2.keepAlive, Rx2.withLabel("graph-builder:extensions"));
|
|
606
|
+
_initialized = {};
|
|
607
|
+
_registry;
|
|
608
|
+
_graph;
|
|
581
609
|
constructor({ registry, ...params } = {}) {
|
|
582
|
-
// TODO(wittjosiah): Use Context.
|
|
583
|
-
this._connectorSubscriptions = /* @__PURE__ */ new Map();
|
|
584
|
-
this._extensions = Rx2.make(Record2.empty()).pipe(Rx2.keepAlive, Rx2.withLabel("graph-builder:extensions"));
|
|
585
|
-
this._connectors = Rx2.family((key) => {
|
|
586
|
-
return Rx2.make((get) => {
|
|
587
|
-
const [id, relation] = key.split("+");
|
|
588
|
-
const node = this._graph.node(id);
|
|
589
|
-
return pipe2(
|
|
590
|
-
get(this._extensions),
|
|
591
|
-
Record2.values,
|
|
592
|
-
// TODO(wittjosiah): Sort on write rather than read.
|
|
593
|
-
Array.sortBy(byPosition),
|
|
594
|
-
Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
595
|
-
Array.map(({ connector }) => connector?.(node)),
|
|
596
|
-
Array.filter(isNonNullable2),
|
|
597
|
-
Array.flatMap((result) => get(result))
|
|
598
|
-
);
|
|
599
|
-
}).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
|
|
600
|
-
});
|
|
601
610
|
this._registry = registry ?? Registry2.make();
|
|
602
611
|
this._graph = new Graph({
|
|
603
612
|
...params,
|
|
604
613
|
registry: this._registry,
|
|
605
614
|
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
606
|
-
|
|
615
|
+
onInitialize: (id) => this._onInitialize(id),
|
|
607
616
|
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
608
617
|
});
|
|
609
618
|
}
|
|
@@ -673,9 +682,30 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
673
682
|
}
|
|
674
683
|
}
|
|
675
684
|
destroy() {
|
|
676
|
-
this.
|
|
677
|
-
this.
|
|
685
|
+
this._subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
686
|
+
this._subscriptions.clear();
|
|
678
687
|
}
|
|
688
|
+
_resolvers = Rx2.family((id) => {
|
|
689
|
+
return Rx2.make((get2) => {
|
|
690
|
+
return Function2.pipe(get2(this._extensions), Record2.values, Array.sortBy(byPosition), Array.map(({ resolver }) => resolver), Array.filter(isNonNullable2), Array.map((resolver) => get2(resolver(id))), Array.filter(isNonNullable2), Array.head);
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
_connectors = Rx2.family((key) => {
|
|
694
|
+
return Rx2.make((get2) => {
|
|
695
|
+
const [id, relation] = key.split("+");
|
|
696
|
+
const node = this._graph.node(id);
|
|
697
|
+
return Function2.pipe(
|
|
698
|
+
get2(this._extensions),
|
|
699
|
+
Record2.values,
|
|
700
|
+
// TODO(wittjosiah): Sort on write rather than read.
|
|
701
|
+
Array.sortBy(byPosition),
|
|
702
|
+
Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
703
|
+
Array.map(({ connector }) => connector?.(node)),
|
|
704
|
+
Array.filter(isNonNullable2),
|
|
705
|
+
Array.flatMap((result) => get2(result))
|
|
706
|
+
);
|
|
707
|
+
}).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
|
|
708
|
+
});
|
|
679
709
|
_onExpand(id, relation) {
|
|
680
710
|
log2("onExpand", {
|
|
681
711
|
id,
|
|
@@ -683,7 +713,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
683
713
|
registry: getDebugName(this._registry)
|
|
684
714
|
}, {
|
|
685
715
|
F: __dxlog_file2,
|
|
686
|
-
L:
|
|
716
|
+
L: 327,
|
|
687
717
|
S: this,
|
|
688
718
|
C: (f, a) => f(...a)
|
|
689
719
|
});
|
|
@@ -700,7 +730,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
700
730
|
removed
|
|
701
731
|
}, {
|
|
702
732
|
F: __dxlog_file2,
|
|
703
|
-
L:
|
|
733
|
+
L: 338,
|
|
704
734
|
S: this,
|
|
705
735
|
C: (f, a) => f(...a)
|
|
706
736
|
});
|
|
@@ -729,30 +759,58 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
729
759
|
}, {
|
|
730
760
|
immediate: true
|
|
731
761
|
});
|
|
732
|
-
this.
|
|
762
|
+
this._subscriptions.set(id, cancel);
|
|
763
|
+
}
|
|
764
|
+
// TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?
|
|
765
|
+
async _onInitialize(id) {
|
|
766
|
+
log2("onInitialize", {
|
|
767
|
+
id
|
|
768
|
+
}, {
|
|
769
|
+
F: __dxlog_file2,
|
|
770
|
+
L: 375,
|
|
771
|
+
S: this,
|
|
772
|
+
C: (f, a) => f(...a)
|
|
773
|
+
});
|
|
774
|
+
const resolver = this._resolvers(id);
|
|
775
|
+
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
776
|
+
const trigger = this._initialized[id];
|
|
777
|
+
Option2.match(node, {
|
|
778
|
+
onSome: (node2) => {
|
|
779
|
+
this._graph.addNodes([
|
|
780
|
+
node2
|
|
781
|
+
]);
|
|
782
|
+
trigger?.wake();
|
|
783
|
+
},
|
|
784
|
+
onNone: () => {
|
|
785
|
+
trigger?.wake();
|
|
786
|
+
this._graph.removeNodes([
|
|
787
|
+
id
|
|
788
|
+
]);
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
}, {
|
|
792
|
+
immediate: true
|
|
793
|
+
});
|
|
794
|
+
this._subscriptions.set(id, cancel);
|
|
733
795
|
}
|
|
734
|
-
// TODO(wittjosiah): On initialize to restore state from cache.
|
|
735
|
-
// private async _onInitialize(id: string) {
|
|
736
|
-
// log('onInitialize', { id });
|
|
737
|
-
// }
|
|
738
796
|
_onRemoveNode(id) {
|
|
739
|
-
this.
|
|
740
|
-
this.
|
|
797
|
+
this._subscriptions.get(id)?.();
|
|
798
|
+
this._subscriptions.delete(id);
|
|
741
799
|
}
|
|
742
800
|
};
|
|
743
801
|
var rxFromSignal = (cb) => {
|
|
744
|
-
return Rx2.make((
|
|
802
|
+
return Rx2.make((get2) => {
|
|
745
803
|
const dispose = effect(() => {
|
|
746
|
-
|
|
804
|
+
get2.setSelf(cb());
|
|
747
805
|
});
|
|
748
|
-
|
|
806
|
+
get2.addFinalizer(() => dispose());
|
|
749
807
|
return cb();
|
|
750
808
|
});
|
|
751
809
|
};
|
|
752
810
|
var observableFamily = Rx2.family((observable) => {
|
|
753
|
-
return Rx2.make((
|
|
754
|
-
const subscription = observable.subscribe((value) =>
|
|
755
|
-
|
|
811
|
+
return Rx2.make((get2) => {
|
|
812
|
+
const subscription = observable.subscribe((value) => get2.setSelf(value));
|
|
813
|
+
get2.addFinalizer(() => subscription.unsubscribe());
|
|
756
814
|
return observable.get();
|
|
757
815
|
});
|
|
758
816
|
});
|