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