@dxos/app-graph 0.8.4-main.84f28bd → 0.8.4-main.a4bbb77
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 +236 -161
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +236 -161
- 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 +6 -2
- 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/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -33
- package/src/graph-builder.test.ts +59 -2
- package/src/graph-builder.ts +65 -21
- package/src/graph.test.ts +1 -1
- package/src/graph.ts +16 -17
- package/src/node.ts +5 -3
- package/src/signals-integration.test.ts +1 -1
- package/src/stories/EchoGraph.stories.tsx +25 -23
|
@@ -2,12 +2,25 @@ 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 { Option,
|
|
5
|
+
import { Option, Record, pipe } from "effect";
|
|
6
6
|
import { Event, Trigger } from "@dxos/async";
|
|
7
7
|
import { todo } from "@dxos/debug";
|
|
8
8
|
import { invariant } from "@dxos/invariant";
|
|
9
9
|
import { log } from "@dxos/log";
|
|
10
10
|
import { isNonNullable } from "@dxos/util";
|
|
11
|
+
function _define_property(obj, key, value) {
|
|
12
|
+
if (key in obj) {
|
|
13
|
+
Object.defineProperty(obj, key, {
|
|
14
|
+
value,
|
|
15
|
+
enumerable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
writable: true
|
|
18
|
+
});
|
|
19
|
+
} else {
|
|
20
|
+
obj[key] = value;
|
|
21
|
+
}
|
|
22
|
+
return obj;
|
|
23
|
+
}
|
|
11
24
|
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
12
25
|
var graphSymbol = Symbol("graph");
|
|
13
26
|
var getGraph = (node) => {
|
|
@@ -28,103 +41,6 @@ var ROOT_TYPE = "dxos.org/type/GraphRoot";
|
|
|
28
41
|
var ACTION_TYPE = "dxos.org/type/GraphAction";
|
|
29
42
|
var ACTION_GROUP_TYPE = "dxos.org/type/GraphActionGroup";
|
|
30
43
|
var Graph = class {
|
|
31
|
-
constructor({ registry, nodes, edges, onExpand, onRemoveNode } = {}) {
|
|
32
|
-
this.onNodeChanged = new Event();
|
|
33
|
-
this._expanded = Record.empty();
|
|
34
|
-
this._initialized = Record.empty();
|
|
35
|
-
this._initialEdges = Record.empty();
|
|
36
|
-
this._initialNodes = Record.fromEntries([
|
|
37
|
-
[
|
|
38
|
-
ROOT_ID,
|
|
39
|
-
this._constructNode({
|
|
40
|
-
id: ROOT_ID,
|
|
41
|
-
type: ROOT_TYPE,
|
|
42
|
-
data: null,
|
|
43
|
-
properties: {}
|
|
44
|
-
})
|
|
45
|
-
]
|
|
46
|
-
]);
|
|
47
|
-
/** @internal */
|
|
48
|
-
this._node = Rx.family((id) => {
|
|
49
|
-
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
50
|
-
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:node:${id}`));
|
|
51
|
-
});
|
|
52
|
-
this._nodeOrThrow = Rx.family((id) => {
|
|
53
|
-
return Rx.make((get) => {
|
|
54
|
-
const node = get(this._node(id));
|
|
55
|
-
invariant(Option.isSome(node), `Node not available: ${id}`, {
|
|
56
|
-
F: __dxlog_file,
|
|
57
|
-
L: 253,
|
|
58
|
-
S: this,
|
|
59
|
-
A: [
|
|
60
|
-
"Option.isSome(node)",
|
|
61
|
-
"`Node not available: ${id}`"
|
|
62
|
-
]
|
|
63
|
-
});
|
|
64
|
-
return node.value;
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
this._edges = Rx.family((id) => {
|
|
68
|
-
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
69
|
-
inbound: [],
|
|
70
|
-
outbound: []
|
|
71
|
-
})));
|
|
72
|
-
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:edges:${id}`));
|
|
73
|
-
});
|
|
74
|
-
// NOTE: Currently the argument to the family needs to be referentially stable for the rx to be referentially stable.
|
|
75
|
-
// TODO(wittjosiah): Rx feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
76
|
-
this._connections = Rx.family((key) => {
|
|
77
|
-
return Rx.make((get) => {
|
|
78
|
-
const [id, relation] = key.split("$");
|
|
79
|
-
const edges = get(this._edges(id));
|
|
80
|
-
return edges[relation].map((id2) => get(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
81
|
-
}).pipe(Rx.withLabel(`graph:connections:${key}`));
|
|
82
|
-
});
|
|
83
|
-
this._actions = Rx.family((id) => {
|
|
84
|
-
return Rx.make((get) => {
|
|
85
|
-
return get(this._connections(`${id}$outbound`)).filter((node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE);
|
|
86
|
-
}).pipe(Rx.withLabel(`graph:actions:${id}`));
|
|
87
|
-
});
|
|
88
|
-
this._json = Rx.family((id) => {
|
|
89
|
-
return Rx.make((get) => {
|
|
90
|
-
const toJSON = (node, seen = []) => {
|
|
91
|
-
const nodes = get(this.connections(node.id));
|
|
92
|
-
const obj = {
|
|
93
|
-
id: node.id.length > 32 ? `${node.id.slice(0, 32)}...` : node.id,
|
|
94
|
-
type: node.type
|
|
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;
|
|
109
|
-
};
|
|
110
|
-
const root = get(this.nodeOrThrow(id));
|
|
111
|
-
return toJSON(root);
|
|
112
|
-
}).pipe(Rx.withLabel(`graph:json:${id}`));
|
|
113
|
-
});
|
|
114
|
-
this._registry = registry ?? Registry.make();
|
|
115
|
-
this._onExpand = onExpand;
|
|
116
|
-
this._onRemoveNode = onRemoveNode;
|
|
117
|
-
if (nodes) {
|
|
118
|
-
nodes.forEach((node) => {
|
|
119
|
-
Record.set(this._initialNodes, node.id, this._constructNode(node));
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
if (edges) {
|
|
123
|
-
Object.entries(edges).forEach(([source, edges2]) => {
|
|
124
|
-
Record.set(this._initialEdges, source, edges2);
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
44
|
toJSON(id = ROOT_ID) {
|
|
129
45
|
return this._registry.get(this._json(id));
|
|
130
46
|
}
|
|
@@ -164,15 +80,22 @@ var Graph = class {
|
|
|
164
80
|
getEdges(id) {
|
|
165
81
|
return this._registry.get(this.edges(id));
|
|
166
82
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
83
|
+
async initialize(id) {
|
|
84
|
+
const initialized = Record.get(this._initialized, id).pipe(Option.getOrElse(() => false));
|
|
85
|
+
log("initialize", {
|
|
86
|
+
id,
|
|
87
|
+
initialized
|
|
88
|
+
}, {
|
|
89
|
+
F: __dxlog_file,
|
|
90
|
+
L: 384,
|
|
91
|
+
S: this,
|
|
92
|
+
C: (f, a) => f(...a)
|
|
93
|
+
});
|
|
94
|
+
if (!initialized) {
|
|
95
|
+
await this._onInitialize?.(id);
|
|
96
|
+
Record.set(this._initialized, id, true);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
176
99
|
expand(id, relation = "outbound") {
|
|
177
100
|
const key = `${id}$${relation}`;
|
|
178
101
|
const expanded = Record.get(this._expanded, key).pipe(Option.getOrElse(() => false));
|
|
@@ -181,7 +104,7 @@ var Graph = class {
|
|
|
181
104
|
expanded
|
|
182
105
|
}, {
|
|
183
106
|
F: __dxlog_file,
|
|
184
|
-
L:
|
|
107
|
+
L: 394,
|
|
185
108
|
S: this,
|
|
186
109
|
C: (f, a) => f(...a)
|
|
187
110
|
});
|
|
@@ -211,7 +134,7 @@ var Graph = class {
|
|
|
211
134
|
propertiesChanged
|
|
212
135
|
}, {
|
|
213
136
|
F: __dxlog_file,
|
|
214
|
-
L:
|
|
137
|
+
L: 416,
|
|
215
138
|
S: this,
|
|
216
139
|
C: (f, a) => f(...a)
|
|
217
140
|
});
|
|
@@ -223,7 +146,7 @@ var Graph = class {
|
|
|
223
146
|
properties
|
|
224
147
|
}, {
|
|
225
148
|
F: __dxlog_file,
|
|
226
|
-
L:
|
|
149
|
+
L: 418,
|
|
227
150
|
S: this,
|
|
228
151
|
C: (f, a) => f(...a)
|
|
229
152
|
});
|
|
@@ -251,7 +174,7 @@ var Graph = class {
|
|
|
251
174
|
properties
|
|
252
175
|
}, {
|
|
253
176
|
F: __dxlog_file,
|
|
254
|
-
L:
|
|
177
|
+
L: 425,
|
|
255
178
|
S: this,
|
|
256
179
|
C: (f, a) => f(...a)
|
|
257
180
|
});
|
|
@@ -322,7 +245,7 @@ var Graph = class {
|
|
|
322
245
|
target: edgeArg.target
|
|
323
246
|
}, {
|
|
324
247
|
F: __dxlog_file,
|
|
325
|
-
L:
|
|
248
|
+
L: 480,
|
|
326
249
|
S: this,
|
|
327
250
|
C: (f, a) => f(...a)
|
|
328
251
|
});
|
|
@@ -342,7 +265,7 @@ var Graph = class {
|
|
|
342
265
|
target: edgeArg.target
|
|
343
266
|
}, {
|
|
344
267
|
F: __dxlog_file,
|
|
345
|
-
L:
|
|
268
|
+
L: 487,
|
|
346
269
|
S: this,
|
|
347
270
|
C: (f, a) => f(...a)
|
|
348
271
|
});
|
|
@@ -466,32 +389,149 @@ var Graph = class {
|
|
|
466
389
|
...node
|
|
467
390
|
});
|
|
468
391
|
}
|
|
392
|
+
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
393
|
+
_define_property(this, "onNodeChanged", new Event());
|
|
394
|
+
_define_property(this, "_onExpand", void 0);
|
|
395
|
+
_define_property(this, "_onInitialize", void 0);
|
|
396
|
+
_define_property(this, "_onRemoveNode", void 0);
|
|
397
|
+
_define_property(this, "_registry", void 0);
|
|
398
|
+
_define_property(this, "_expanded", Record.empty());
|
|
399
|
+
_define_property(this, "_initialized", Record.empty());
|
|
400
|
+
_define_property(this, "_initialEdges", Record.empty());
|
|
401
|
+
_define_property(this, "_initialNodes", Record.fromEntries([
|
|
402
|
+
[
|
|
403
|
+
ROOT_ID,
|
|
404
|
+
this._constructNode({
|
|
405
|
+
id: ROOT_ID,
|
|
406
|
+
type: ROOT_TYPE,
|
|
407
|
+
data: null,
|
|
408
|
+
properties: {}
|
|
409
|
+
})
|
|
410
|
+
]
|
|
411
|
+
]));
|
|
412
|
+
_define_property(this, "_node", Rx.family((id) => {
|
|
413
|
+
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
414
|
+
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:node:${id}`));
|
|
415
|
+
}));
|
|
416
|
+
_define_property(this, "_nodeOrThrow", Rx.family((id) => {
|
|
417
|
+
return Rx.make((get) => {
|
|
418
|
+
const node = get(this._node(id));
|
|
419
|
+
invariant(Option.isSome(node), `Node not available: ${id}`, {
|
|
420
|
+
F: __dxlog_file,
|
|
421
|
+
L: 252,
|
|
422
|
+
S: this,
|
|
423
|
+
A: [
|
|
424
|
+
"Option.isSome(node)",
|
|
425
|
+
"`Node not available: ${id}`"
|
|
426
|
+
]
|
|
427
|
+
});
|
|
428
|
+
return node.value;
|
|
429
|
+
});
|
|
430
|
+
}));
|
|
431
|
+
_define_property(this, "_edges", Rx.family((id) => {
|
|
432
|
+
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
433
|
+
inbound: [],
|
|
434
|
+
outbound: []
|
|
435
|
+
})));
|
|
436
|
+
return Rx.make(initial).pipe(Rx.keepAlive, Rx.withLabel(`graph:edges:${id}`));
|
|
437
|
+
}));
|
|
438
|
+
_define_property(this, "_connections", Rx.family((key) => {
|
|
439
|
+
return Rx.make((get) => {
|
|
440
|
+
const [id, relation] = key.split("$");
|
|
441
|
+
const edges2 = get(this._edges(id));
|
|
442
|
+
return edges2[relation].map((id2) => get(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
443
|
+
}).pipe(Rx.withLabel(`graph:connections:${key}`));
|
|
444
|
+
}));
|
|
445
|
+
_define_property(this, "_actions", Rx.family((id) => {
|
|
446
|
+
return Rx.make((get) => {
|
|
447
|
+
return get(this._connections(`${id}$outbound`)).filter((node) => node.type === ACTION_TYPE || node.type === ACTION_GROUP_TYPE);
|
|
448
|
+
}).pipe(Rx.withLabel(`graph:actions:${id}`));
|
|
449
|
+
}));
|
|
450
|
+
_define_property(this, "_json", Rx.family((id) => {
|
|
451
|
+
return Rx.make((get) => {
|
|
452
|
+
const toJSON = (node, seen = []) => {
|
|
453
|
+
const nodes2 = get(this.connections(node.id));
|
|
454
|
+
const obj = {
|
|
455
|
+
id: node.id.length > 32 ? `${node.id.slice(0, 32)}...` : node.id,
|
|
456
|
+
type: node.type
|
|
457
|
+
};
|
|
458
|
+
if (node.properties.label) {
|
|
459
|
+
obj.label = node.properties.label;
|
|
460
|
+
}
|
|
461
|
+
if (nodes2.length) {
|
|
462
|
+
obj.nodes = nodes2.map((n) => {
|
|
463
|
+
const nextSeen = [
|
|
464
|
+
...seen,
|
|
465
|
+
node.id
|
|
466
|
+
];
|
|
467
|
+
return nextSeen.includes(n.id) ? void 0 : toJSON(n, nextSeen);
|
|
468
|
+
}).filter(isNonNullable);
|
|
469
|
+
}
|
|
470
|
+
return obj;
|
|
471
|
+
};
|
|
472
|
+
const root = get(this.nodeOrThrow(id));
|
|
473
|
+
return toJSON(root);
|
|
474
|
+
}).pipe(Rx.withLabel(`graph:json:${id}`));
|
|
475
|
+
}));
|
|
476
|
+
this._registry = registry ?? Registry.make();
|
|
477
|
+
this._onInitialize = onInitialize;
|
|
478
|
+
this._onExpand = onExpand;
|
|
479
|
+
this._onRemoveNode = onRemoveNode;
|
|
480
|
+
if (nodes) {
|
|
481
|
+
nodes.forEach((node) => {
|
|
482
|
+
Record.set(this._initialNodes, node.id, this._constructNode(node));
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (edges) {
|
|
486
|
+
Object.entries(edges).forEach(([source, edges2]) => {
|
|
487
|
+
Record.set(this._initialEdges, source, edges2);
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
}
|
|
469
491
|
};
|
|
470
492
|
|
|
471
493
|
// src/graph-builder.ts
|
|
472
494
|
import { Registry as Registry2, Rx as Rx2 } from "@effect-rx/rx-react";
|
|
473
495
|
import { effect } from "@preact/signals-core";
|
|
474
|
-
import { Array,
|
|
496
|
+
import { Array, Option as Option2, Record as Record2, pipe as pipe2 } from "effect";
|
|
475
497
|
import { log as log2 } from "@dxos/log";
|
|
476
498
|
import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
477
499
|
|
|
478
500
|
// src/node.ts
|
|
479
501
|
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;
|
|
502
|
+
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" && data.type === ACTION_TYPE : false;
|
|
481
503
|
var actionGroupSymbol = Symbol("ActionGroup");
|
|
482
|
-
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol : false;
|
|
504
|
+
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ACTION_GROUP_TYPE : false;
|
|
483
505
|
var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
484
506
|
|
|
485
507
|
// src/graph-builder.ts
|
|
508
|
+
function _define_property2(obj, key, value) {
|
|
509
|
+
if (key in obj) {
|
|
510
|
+
Object.defineProperty(obj, key, {
|
|
511
|
+
value,
|
|
512
|
+
enumerable: true,
|
|
513
|
+
configurable: true,
|
|
514
|
+
writable: true
|
|
515
|
+
});
|
|
516
|
+
} else {
|
|
517
|
+
obj[key] = value;
|
|
518
|
+
}
|
|
519
|
+
return obj;
|
|
520
|
+
}
|
|
486
521
|
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
487
522
|
var createExtension = (extension) => {
|
|
488
|
-
const { id, position = "static", relation = "outbound", connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
523
|
+
const { id, position = "static", relation = "outbound", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
489
524
|
const getId = (key) => `${id}/${key}`;
|
|
525
|
+
const resolver = _resolver && Rx2.family((id2) => _resolver(id2).pipe(Rx2.withLabel(`graph-builder:_resolver:${id2}`)));
|
|
490
526
|
const connector = _connector && Rx2.family((node) => _connector(node).pipe(Rx2.withLabel(`graph-builder:_connector:${id}`)));
|
|
491
527
|
const actionGroups = _actionGroups && Rx2.family((node) => _actionGroups(node).pipe(Rx2.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
492
528
|
const actions = _actions && Rx2.family((node) => _actions(node).pipe(Rx2.withLabel(`graph-builder:_actions:${id}`)));
|
|
493
529
|
return [
|
|
494
|
-
|
|
530
|
+
resolver ? {
|
|
531
|
+
id: getId("resolver"),
|
|
532
|
+
position,
|
|
533
|
+
resolver
|
|
534
|
+
} : void 0,
|
|
495
535
|
connector ? {
|
|
496
536
|
id: getId("connector"),
|
|
497
537
|
position,
|
|
@@ -505,7 +545,7 @@ var createExtension = (extension) => {
|
|
|
505
545
|
node
|
|
506
546
|
}, {
|
|
507
547
|
F: __dxlog_file2,
|
|
508
|
-
L:
|
|
548
|
+
L: 109,
|
|
509
549
|
S: void 0,
|
|
510
550
|
C: (f, a) => f(...a)
|
|
511
551
|
});
|
|
@@ -530,7 +570,7 @@ var createExtension = (extension) => {
|
|
|
530
570
|
node
|
|
531
571
|
}, {
|
|
532
572
|
F: __dxlog_file2,
|
|
533
|
-
L:
|
|
573
|
+
L: 130,
|
|
534
574
|
S: void 0,
|
|
535
575
|
C: (f, a) => f(...a)
|
|
536
576
|
});
|
|
@@ -554,7 +594,7 @@ var createExtension = (extension) => {
|
|
|
554
594
|
node
|
|
555
595
|
}, {
|
|
556
596
|
F: __dxlog_file2,
|
|
557
|
-
L:
|
|
597
|
+
L: 147,
|
|
558
598
|
S: void 0,
|
|
559
599
|
C: (f, a) => f(...a)
|
|
560
600
|
});
|
|
@@ -578,35 +618,6 @@ var flattenExtensions = (extension, acc = []) => {
|
|
|
578
618
|
}
|
|
579
619
|
};
|
|
580
620
|
var GraphBuilder = class _GraphBuilder {
|
|
581
|
-
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
|
-
this._registry = registry ?? Registry2.make();
|
|
602
|
-
this._graph = new Graph({
|
|
603
|
-
...params,
|
|
604
|
-
registry: this._registry,
|
|
605
|
-
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
606
|
-
// onInitialize: (id) => this._onInitialize(id),
|
|
607
|
-
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
621
|
static from(pickle, registry) {
|
|
611
622
|
if (!pickle) {
|
|
612
623
|
return new _GraphBuilder({
|
|
@@ -673,8 +684,8 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
673
684
|
}
|
|
674
685
|
}
|
|
675
686
|
destroy() {
|
|
676
|
-
this.
|
|
677
|
-
this.
|
|
687
|
+
this._subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
688
|
+
this._subscriptions.clear();
|
|
678
689
|
}
|
|
679
690
|
_onExpand(id, relation) {
|
|
680
691
|
log2("onExpand", {
|
|
@@ -683,7 +694,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
683
694
|
registry: getDebugName(this._registry)
|
|
684
695
|
}, {
|
|
685
696
|
F: __dxlog_file2,
|
|
686
|
-
L:
|
|
697
|
+
L: 324,
|
|
687
698
|
S: this,
|
|
688
699
|
C: (f, a) => f(...a)
|
|
689
700
|
});
|
|
@@ -700,7 +711,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
700
711
|
removed
|
|
701
712
|
}, {
|
|
702
713
|
F: __dxlog_file2,
|
|
703
|
-
L:
|
|
714
|
+
L: 335,
|
|
704
715
|
S: this,
|
|
705
716
|
C: (f, a) => f(...a)
|
|
706
717
|
});
|
|
@@ -729,15 +740,79 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
729
740
|
}, {
|
|
730
741
|
immediate: true
|
|
731
742
|
});
|
|
732
|
-
this.
|
|
743
|
+
this._subscriptions.set(id, cancel);
|
|
744
|
+
}
|
|
745
|
+
// TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?
|
|
746
|
+
async _onInitialize(id) {
|
|
747
|
+
log2("onInitialize", {
|
|
748
|
+
id
|
|
749
|
+
}, {
|
|
750
|
+
F: __dxlog_file2,
|
|
751
|
+
L: 372,
|
|
752
|
+
S: this,
|
|
753
|
+
C: (f, a) => f(...a)
|
|
754
|
+
});
|
|
755
|
+
const resolver = this._resolvers(id);
|
|
756
|
+
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
757
|
+
const trigger = this._initialized[id];
|
|
758
|
+
Option2.match(node, {
|
|
759
|
+
onSome: (node2) => {
|
|
760
|
+
this._graph.addNodes([
|
|
761
|
+
node2
|
|
762
|
+
]);
|
|
763
|
+
trigger?.wake();
|
|
764
|
+
},
|
|
765
|
+
onNone: () => {
|
|
766
|
+
trigger?.wake();
|
|
767
|
+
this._graph.removeNodes([
|
|
768
|
+
id
|
|
769
|
+
]);
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
}, {
|
|
773
|
+
immediate: true
|
|
774
|
+
});
|
|
775
|
+
this._subscriptions.set(id, cancel);
|
|
733
776
|
}
|
|
734
|
-
// TODO(wittjosiah): On initialize to restore state from cache.
|
|
735
|
-
// private async _onInitialize(id: string) {
|
|
736
|
-
// log('onInitialize', { id });
|
|
737
|
-
// }
|
|
738
777
|
_onRemoveNode(id) {
|
|
739
|
-
this.
|
|
740
|
-
this.
|
|
778
|
+
this._subscriptions.get(id)?.();
|
|
779
|
+
this._subscriptions.delete(id);
|
|
780
|
+
}
|
|
781
|
+
constructor({ registry, ...params } = {}) {
|
|
782
|
+
_define_property2(this, "_subscriptions", /* @__PURE__ */ new Map());
|
|
783
|
+
_define_property2(this, "_extensions", Rx2.make(Record2.empty()).pipe(Rx2.keepAlive, Rx2.withLabel("graph-builder:extensions")));
|
|
784
|
+
_define_property2(this, "_initialized", {});
|
|
785
|
+
_define_property2(this, "_registry", void 0);
|
|
786
|
+
_define_property2(this, "_graph", void 0);
|
|
787
|
+
_define_property2(this, "_resolvers", Rx2.family((id) => {
|
|
788
|
+
return Rx2.make((get) => {
|
|
789
|
+
return pipe2(get(this._extensions), Record2.values, Array.sortBy(byPosition), Array.map(({ resolver }) => resolver), Array.filter(isNonNullable2), Array.map((resolver) => get(resolver(id))), Array.filter(isNonNullable2), Array.head);
|
|
790
|
+
});
|
|
791
|
+
}));
|
|
792
|
+
_define_property2(this, "_connectors", Rx2.family((key) => {
|
|
793
|
+
return Rx2.make((get) => {
|
|
794
|
+
const [id, relation] = key.split("+");
|
|
795
|
+
const node = this._graph.node(id);
|
|
796
|
+
return pipe2(
|
|
797
|
+
get(this._extensions),
|
|
798
|
+
Record2.values,
|
|
799
|
+
// TODO(wittjosiah): Sort on write rather than read.
|
|
800
|
+
Array.sortBy(byPosition),
|
|
801
|
+
Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
802
|
+
Array.map(({ connector }) => connector?.(node)),
|
|
803
|
+
Array.filter(isNonNullable2),
|
|
804
|
+
Array.flatMap((result) => get(result))
|
|
805
|
+
);
|
|
806
|
+
}).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
|
|
807
|
+
}));
|
|
808
|
+
this._registry = registry ?? Registry2.make();
|
|
809
|
+
this._graph = new Graph({
|
|
810
|
+
...params,
|
|
811
|
+
registry: this._registry,
|
|
812
|
+
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
813
|
+
onInitialize: (id) => this._onInitialize(id),
|
|
814
|
+
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
815
|
+
});
|
|
741
816
|
}
|
|
742
817
|
};
|
|
743
818
|
var rxFromSignal = (cb) => {
|