@dxos/app-graph 0.8.4-main.1da679c → 0.8.4-main.21d9917
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 +1111 -667
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1110 -667
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/atoms.d.ts +8 -0
- package/dist/types/src/atoms.d.ts.map +1 -0
- package/dist/types/src/graph-builder.d.ts +109 -67
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +183 -213
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +6 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/node-matcher.d.ts +218 -0
- package/dist/types/src/node-matcher.d.ts.map +1 -0
- package/dist/types/src/node-matcher.test.d.ts +2 -0
- package/dist/types/src/node-matcher.test.d.ts.map +1 -0
- package/dist/types/src/node.d.ts +32 -3
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts +0 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +36 -35
- package/src/atoms.ts +25 -0
- package/src/graph-builder.test.ts +528 -111
- package/src/graph-builder.ts +557 -259
- package/src/graph.test.ts +300 -107
- package/src/graph.ts +968 -396
- package/src/index.ts +9 -3
- package/src/node-matcher.test.ts +301 -0
- package/src/node-matcher.ts +284 -0
- package/src/node.ts +39 -6
- package/src/stories/EchoGraph.stories.tsx +111 -103
- package/src/stories/Tree.tsx +2 -2
- package/dist/types/src/experimental/graph-projections.test.d.ts +0 -25
- package/dist/types/src/experimental/graph-projections.test.d.ts.map +0 -1
- package/dist/types/src/signals-integration.test.d.ts +0 -2
- package/dist/types/src/signals-integration.test.d.ts.map +0 -1
- package/dist/types/src/testing.d.ts +0 -5
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/experimental/graph-projections.test.ts +0 -56
- package/src/signals-integration.test.ts +0 -218
- package/src/testing.ts +0 -20
|
@@ -1,31 +1,97 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/atoms.ts
|
|
8
|
+
var atoms_exports = {};
|
|
9
|
+
__export(atoms_exports, {
|
|
10
|
+
fromObservable: () => fromObservable
|
|
11
|
+
});
|
|
12
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
13
|
+
var observableFamily = Atom.family((observable) => {
|
|
14
|
+
return Atom.make((get2) => {
|
|
15
|
+
const subscription = observable.subscribe((value) => get2.setSelf(value));
|
|
16
|
+
get2.addFinalizer(() => subscription.unsubscribe());
|
|
17
|
+
return observable.get();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
var fromObservable = (observable) => {
|
|
21
|
+
return observableFamily(observable);
|
|
22
|
+
};
|
|
23
|
+
|
|
1
24
|
// src/graph.ts
|
|
2
|
-
|
|
3
|
-
|
|
25
|
+
var graph_exports = {};
|
|
26
|
+
__export(graph_exports, {
|
|
27
|
+
GraphKind: () => GraphKind,
|
|
28
|
+
GraphTypeId: () => GraphTypeId,
|
|
29
|
+
addEdge: () => addEdge,
|
|
30
|
+
addEdges: () => addEdges,
|
|
31
|
+
addNode: () => addNode,
|
|
32
|
+
addNodes: () => addNodes,
|
|
33
|
+
expand: () => expand,
|
|
34
|
+
getActions: () => getActions,
|
|
35
|
+
getConnections: () => getConnections,
|
|
36
|
+
getEdges: () => getEdges,
|
|
37
|
+
getGraph: () => getGraph,
|
|
38
|
+
getNode: () => getNode,
|
|
39
|
+
getNodeOrThrow: () => getNodeOrThrow,
|
|
40
|
+
getPath: () => getPath,
|
|
41
|
+
getRoot: () => getRoot,
|
|
42
|
+
initialize: () => initialize,
|
|
43
|
+
make: () => make,
|
|
44
|
+
removeEdge: () => removeEdge,
|
|
45
|
+
removeEdges: () => removeEdges,
|
|
46
|
+
removeNode: () => removeNode,
|
|
47
|
+
removeNodes: () => removeNodes,
|
|
48
|
+
sortEdges: () => sortEdges,
|
|
49
|
+
toJSON: () => toJSON,
|
|
50
|
+
traverse: () => traverse,
|
|
51
|
+
waitForPath: () => waitForPath
|
|
52
|
+
});
|
|
53
|
+
import { Atom as Atom2, Registry } from "@effect-atom/atom-react";
|
|
54
|
+
import * as Function from "effect/Function";
|
|
55
|
+
import * as Option from "effect/Option";
|
|
56
|
+
import * as Pipeable from "effect/Pipeable";
|
|
57
|
+
import * as Record from "effect/Record";
|
|
4
58
|
import { Event, Trigger } from "@dxos/async";
|
|
5
59
|
import { todo } from "@dxos/debug";
|
|
6
60
|
import { invariant } from "@dxos/invariant";
|
|
7
61
|
import { log } from "@dxos/log";
|
|
8
62
|
import { isNonNullable } from "@dxos/util";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
63
|
+
|
|
64
|
+
// src/node.ts
|
|
65
|
+
var node_exports = {};
|
|
66
|
+
__export(node_exports, {
|
|
67
|
+
ActionGroupType: () => ActionGroupType,
|
|
68
|
+
ActionType: () => ActionType,
|
|
69
|
+
RootId: () => RootId,
|
|
70
|
+
RootType: () => RootType,
|
|
71
|
+
actionGroupSymbol: () => actionGroupSymbol,
|
|
72
|
+
isAction: () => isAction,
|
|
73
|
+
isActionGroup: () => isActionGroup,
|
|
74
|
+
isActionLike: () => isActionLike,
|
|
75
|
+
isGraphNode: () => isGraphNode
|
|
76
|
+
});
|
|
77
|
+
var RootId = "root";
|
|
78
|
+
var RootType = "dxos.org/type/GraphRoot";
|
|
79
|
+
var ActionType = "dxos.org/type/GraphAction";
|
|
80
|
+
var ActionGroupType = "dxos.org/type/GraphActionGroup";
|
|
81
|
+
var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
|
|
82
|
+
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" && data.type === ActionType : false;
|
|
83
|
+
var actionGroupSymbol = Symbol("ActionGroup");
|
|
84
|
+
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ActionGroupType : false;
|
|
85
|
+
var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
86
|
+
|
|
87
|
+
// src/graph.ts
|
|
22
88
|
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
23
89
|
var graphSymbol = Symbol("graph");
|
|
24
90
|
var getGraph = (node) => {
|
|
25
91
|
const graph = node[graphSymbol];
|
|
26
92
|
invariant(graph, "Node is not associated with a graph.", {
|
|
27
93
|
F: __dxlog_file,
|
|
28
|
-
L:
|
|
94
|
+
L: 32,
|
|
29
95
|
S: void 0,
|
|
30
96
|
A: [
|
|
31
97
|
"graph",
|
|
@@ -34,600 +100,815 @@ var getGraph = (node) => {
|
|
|
34
100
|
});
|
|
35
101
|
return graph;
|
|
36
102
|
};
|
|
37
|
-
var
|
|
38
|
-
var
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return
|
|
103
|
+
var GraphTypeId = Symbol.for("@dxos/app-graph/Graph");
|
|
104
|
+
var GraphKind = Symbol.for("@dxos/app-graph/GraphKind");
|
|
105
|
+
var GraphImpl = class {
|
|
106
|
+
[GraphTypeId] = GraphTypeId;
|
|
107
|
+
[GraphKind] = "writable";
|
|
108
|
+
pipe() {
|
|
109
|
+
return Pipeable.pipeArguments(this, arguments);
|
|
44
110
|
}
|
|
45
|
-
|
|
46
|
-
|
|
111
|
+
onNodeChanged = new Event();
|
|
112
|
+
_onExpand;
|
|
113
|
+
_onInitialize;
|
|
114
|
+
_onRemoveNode;
|
|
115
|
+
_registry;
|
|
116
|
+
_expanded = Record.empty();
|
|
117
|
+
_initialized = Record.empty();
|
|
118
|
+
_initialEdges = Record.empty();
|
|
119
|
+
_initialNodes = Record.fromEntries([
|
|
120
|
+
[
|
|
121
|
+
RootId,
|
|
122
|
+
this._constructNode({
|
|
123
|
+
id: RootId,
|
|
124
|
+
type: RootType,
|
|
125
|
+
data: null,
|
|
126
|
+
properties: {}
|
|
127
|
+
})
|
|
128
|
+
]
|
|
129
|
+
]);
|
|
130
|
+
/** @internal */
|
|
131
|
+
_node = Atom2.family((id) => {
|
|
132
|
+
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
133
|
+
return Atom2.make(initial).pipe(Atom2.keepAlive, Atom2.withLabel(`graph:node:${id}`));
|
|
134
|
+
});
|
|
135
|
+
_nodeOrThrow = Atom2.family((id) => {
|
|
136
|
+
return Atom2.make((get2) => {
|
|
137
|
+
const node = get2(this._node(id));
|
|
138
|
+
invariant(Option.isSome(node), `Node not available: ${id}`, {
|
|
139
|
+
F: __dxlog_file,
|
|
140
|
+
L: 174,
|
|
141
|
+
S: this,
|
|
142
|
+
A: [
|
|
143
|
+
"Option.isSome(node)",
|
|
144
|
+
"`Node not available: ${id}`"
|
|
145
|
+
]
|
|
146
|
+
});
|
|
147
|
+
return node.value;
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
_edges = Atom2.family((id) => {
|
|
151
|
+
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
152
|
+
inbound: [],
|
|
153
|
+
outbound: []
|
|
154
|
+
})));
|
|
155
|
+
return Atom2.make(initial).pipe(Atom2.keepAlive, Atom2.withLabel(`graph:edges:${id}`));
|
|
156
|
+
});
|
|
157
|
+
// NOTE: Currently the argument to the family needs to be referentially stable for the atom to be referentially stable.
|
|
158
|
+
// TODO(wittjosiah): Atom feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
159
|
+
_connections = Atom2.family((key) => {
|
|
160
|
+
return Atom2.make((get2) => {
|
|
161
|
+
const [id, relation] = key.split("$");
|
|
162
|
+
const edges = get2(this._edges(id));
|
|
163
|
+
return edges[relation].map((id2) => get2(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
164
|
+
}).pipe(Atom2.withLabel(`graph:connections:${key}`));
|
|
165
|
+
});
|
|
166
|
+
_actions = Atom2.family((id) => {
|
|
167
|
+
return Atom2.make((get2) => {
|
|
168
|
+
return get2(this._connections(`${id}$outbound`)).filter((node) => node.type === ActionType || node.type === ActionGroupType);
|
|
169
|
+
}).pipe(Atom2.withLabel(`graph:actions:${id}`));
|
|
170
|
+
});
|
|
171
|
+
_json = Atom2.family((id) => {
|
|
172
|
+
return Atom2.make((get2) => {
|
|
173
|
+
const toJSON2 = (node, seen = []) => {
|
|
174
|
+
const nodes = get2(this._connections(`${node.id}$outbound`));
|
|
175
|
+
const obj = {
|
|
176
|
+
id: node.id,
|
|
177
|
+
type: node.type
|
|
178
|
+
};
|
|
179
|
+
if (node.properties.label) {
|
|
180
|
+
obj.label = node.properties.label;
|
|
181
|
+
}
|
|
182
|
+
if (nodes.length) {
|
|
183
|
+
obj.nodes = nodes.map((n) => {
|
|
184
|
+
const nextSeen = [
|
|
185
|
+
...seen,
|
|
186
|
+
node.id
|
|
187
|
+
];
|
|
188
|
+
return nextSeen.includes(n.id) ? void 0 : toJSON2(n, nextSeen);
|
|
189
|
+
}).filter(isNonNullable);
|
|
190
|
+
}
|
|
191
|
+
return obj;
|
|
192
|
+
};
|
|
193
|
+
const root = get2(this._nodeOrThrow(id));
|
|
194
|
+
return toJSON2(root);
|
|
195
|
+
}).pipe(Atom2.withLabel(`graph:json:${id}`));
|
|
196
|
+
});
|
|
197
|
+
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
198
|
+
this._registry = registry ?? Registry.make();
|
|
199
|
+
this._onInitialize = onInitialize;
|
|
200
|
+
this._onExpand = onExpand;
|
|
201
|
+
this._onRemoveNode = onRemoveNode;
|
|
202
|
+
if (nodes) {
|
|
203
|
+
nodes.forEach((node) => {
|
|
204
|
+
Record.set(this._initialNodes, node.id, this._constructNode(node));
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (edges) {
|
|
208
|
+
Object.entries(edges).forEach(([source, edges2]) => {
|
|
209
|
+
Record.set(this._initialEdges, source, edges2);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
json(id = RootId) {
|
|
214
|
+
return jsonImpl(this, id);
|
|
47
215
|
}
|
|
48
216
|
node(id) {
|
|
49
|
-
return this
|
|
217
|
+
return nodeImpl(this, id);
|
|
50
218
|
}
|
|
51
219
|
nodeOrThrow(id) {
|
|
52
|
-
return this
|
|
220
|
+
return nodeOrThrowImpl(this, id);
|
|
53
221
|
}
|
|
54
222
|
connections(id, relation = "outbound") {
|
|
55
|
-
return this
|
|
223
|
+
return connectionsImpl(this, id, relation);
|
|
56
224
|
}
|
|
57
225
|
actions(id) {
|
|
58
|
-
return this
|
|
226
|
+
return actionsImpl(this, id);
|
|
59
227
|
}
|
|
60
228
|
edges(id) {
|
|
61
|
-
return this
|
|
229
|
+
return edgesImpl(this, id);
|
|
230
|
+
}
|
|
231
|
+
/** @internal */
|
|
232
|
+
_constructNode(node) {
|
|
233
|
+
return Option.some({
|
|
234
|
+
[graphSymbol]: this,
|
|
235
|
+
data: null,
|
|
236
|
+
properties: {},
|
|
237
|
+
...node
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
var getInternal = (graph) => {
|
|
242
|
+
return graph;
|
|
243
|
+
};
|
|
244
|
+
var toJSON = (graph, id = RootId) => {
|
|
245
|
+
const internal = getInternal(graph);
|
|
246
|
+
return internal._registry.get(internal._json(id));
|
|
247
|
+
};
|
|
248
|
+
var jsonImpl = (graph, id = RootId) => {
|
|
249
|
+
const internal = getInternal(graph);
|
|
250
|
+
return internal._json(id);
|
|
251
|
+
};
|
|
252
|
+
var nodeImpl = (graph, id) => {
|
|
253
|
+
const internal = getInternal(graph);
|
|
254
|
+
return internal._node(id);
|
|
255
|
+
};
|
|
256
|
+
var nodeOrThrowImpl = (graph, id) => {
|
|
257
|
+
const internal = getInternal(graph);
|
|
258
|
+
return internal._nodeOrThrow(id);
|
|
259
|
+
};
|
|
260
|
+
var connectionsImpl = (graph, id, relation = "outbound") => {
|
|
261
|
+
const internal = getInternal(graph);
|
|
262
|
+
return internal._connections(`${id}$${relation}`);
|
|
263
|
+
};
|
|
264
|
+
var actionsImpl = (graph, id) => {
|
|
265
|
+
const internal = getInternal(graph);
|
|
266
|
+
return internal._actions(id);
|
|
267
|
+
};
|
|
268
|
+
var edgesImpl = (graph, id) => {
|
|
269
|
+
const internal = getInternal(graph);
|
|
270
|
+
return internal._edges(id);
|
|
271
|
+
};
|
|
272
|
+
var getNodeImpl = (graph, id) => {
|
|
273
|
+
const internal = getInternal(graph);
|
|
274
|
+
return internal._registry.get(nodeImpl(graph, id));
|
|
275
|
+
};
|
|
276
|
+
function getNode(graphOrId, id) {
|
|
277
|
+
if (typeof graphOrId === "string") {
|
|
278
|
+
const id2 = graphOrId;
|
|
279
|
+
return (graph) => getNodeImpl(graph, id2);
|
|
280
|
+
} else {
|
|
281
|
+
const graph = graphOrId;
|
|
282
|
+
return getNodeImpl(graph, id);
|
|
62
283
|
}
|
|
63
|
-
|
|
64
|
-
|
|
284
|
+
}
|
|
285
|
+
var getNodeOrThrowImpl = (graph, id) => {
|
|
286
|
+
const internal = getInternal(graph);
|
|
287
|
+
return internal._registry.get(nodeOrThrowImpl(graph, id));
|
|
288
|
+
};
|
|
289
|
+
function getNodeOrThrow(graphOrId, id) {
|
|
290
|
+
if (typeof graphOrId === "string") {
|
|
291
|
+
const id2 = graphOrId;
|
|
292
|
+
return (graph) => getNodeOrThrowImpl(graph, id2);
|
|
293
|
+
} else {
|
|
294
|
+
const graph = graphOrId;
|
|
295
|
+
return getNodeOrThrowImpl(graph, id);
|
|
65
296
|
}
|
|
66
|
-
|
|
67
|
-
|
|
297
|
+
}
|
|
298
|
+
function getRoot(graph) {
|
|
299
|
+
return getNodeOrThrowImpl(graph, RootId);
|
|
300
|
+
}
|
|
301
|
+
var getConnectionsImpl = (graph, id, relation = "outbound") => {
|
|
302
|
+
const internal = getInternal(graph);
|
|
303
|
+
return internal._registry.get(connectionsImpl(graph, id, relation));
|
|
304
|
+
};
|
|
305
|
+
function getConnections(graphOrId, idOrRelation, relation) {
|
|
306
|
+
if (typeof graphOrId === "string") {
|
|
307
|
+
const id = graphOrId;
|
|
308
|
+
const rel = (typeof idOrRelation === "string" ? "outbound" : idOrRelation) ?? "outbound";
|
|
309
|
+
return (graph) => getConnectionsImpl(graph, id, rel);
|
|
310
|
+
} else {
|
|
311
|
+
const graph = graphOrId;
|
|
312
|
+
const id = idOrRelation;
|
|
313
|
+
const rel = relation ?? "outbound";
|
|
314
|
+
return getConnectionsImpl(graph, id, rel);
|
|
68
315
|
}
|
|
69
|
-
|
|
70
|
-
|
|
316
|
+
}
|
|
317
|
+
var getActionsImpl = (graph, id) => {
|
|
318
|
+
const internal = getInternal(graph);
|
|
319
|
+
return internal._registry.get(actionsImpl(graph, id));
|
|
320
|
+
};
|
|
321
|
+
function getActions(graphOrId, id) {
|
|
322
|
+
if (typeof graphOrId === "string") {
|
|
323
|
+
const id2 = graphOrId;
|
|
324
|
+
return (graph) => getActionsImpl(graph, id2);
|
|
325
|
+
} else {
|
|
326
|
+
const graph = graphOrId;
|
|
327
|
+
return getActionsImpl(graph, id);
|
|
71
328
|
}
|
|
72
|
-
|
|
73
|
-
|
|
329
|
+
}
|
|
330
|
+
var getEdgesImpl = (graph, id) => {
|
|
331
|
+
const internal = getInternal(graph);
|
|
332
|
+
return internal._registry.get(edgesImpl(graph, id));
|
|
333
|
+
};
|
|
334
|
+
function getEdges(graphOrId, id) {
|
|
335
|
+
if (typeof graphOrId === "string") {
|
|
336
|
+
const id2 = graphOrId;
|
|
337
|
+
return (graph) => getEdgesImpl(graph, id2);
|
|
338
|
+
} else {
|
|
339
|
+
const graph = graphOrId;
|
|
340
|
+
return getEdgesImpl(graph, id);
|
|
74
341
|
}
|
|
75
|
-
|
|
76
|
-
|
|
342
|
+
}
|
|
343
|
+
var traverseImpl = (graph, options, path = []) => {
|
|
344
|
+
const { visitor, source = RootId, relation = "outbound" } = options;
|
|
345
|
+
if (path.includes(source)) {
|
|
346
|
+
return;
|
|
77
347
|
}
|
|
78
|
-
|
|
79
|
-
|
|
348
|
+
const node = getNodeOrThrow(graph, source);
|
|
349
|
+
const shouldContinue = visitor(node, [
|
|
350
|
+
...path,
|
|
351
|
+
source
|
|
352
|
+
]);
|
|
353
|
+
if (shouldContinue === false) {
|
|
354
|
+
return;
|
|
80
355
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
356
|
+
Object.values(getConnections(graph, source, relation)).forEach((child) => traverseImpl(graph, {
|
|
357
|
+
source: child.id,
|
|
358
|
+
relation,
|
|
359
|
+
visitor
|
|
360
|
+
}, [
|
|
361
|
+
...path,
|
|
362
|
+
source
|
|
363
|
+
]));
|
|
364
|
+
};
|
|
365
|
+
function traverse(graphOrOptions, optionsOrPath, path) {
|
|
366
|
+
if (typeof graphOrOptions === "object" && "visitor" in graphOrOptions) {
|
|
367
|
+
const options = graphOrOptions;
|
|
368
|
+
const pathArg = Array.isArray(optionsOrPath) ? optionsOrPath : void 0;
|
|
369
|
+
return (graph) => traverseImpl(graph, options, pathArg);
|
|
370
|
+
} else {
|
|
371
|
+
const graph = graphOrOptions;
|
|
372
|
+
const options = optionsOrPath;
|
|
373
|
+
const pathArg = path ?? (Array.isArray(optionsOrPath) ? optionsOrPath : void 0);
|
|
374
|
+
return traverseImpl(graph, options, pathArg);
|
|
96
375
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
376
|
+
}
|
|
377
|
+
var getPathImpl = (graph, params) => {
|
|
378
|
+
return Function.pipe(getNode(graph, params.source ?? "root"), Option.flatMap((node) => {
|
|
379
|
+
let found = Option.none();
|
|
380
|
+
traverseImpl(graph, {
|
|
381
|
+
source: node.id,
|
|
382
|
+
visitor: (node2, path) => {
|
|
383
|
+
if (Option.isSome(found)) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
if (node2.id === params.target) {
|
|
387
|
+
found = Option.some(path);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
108
390
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
391
|
+
return found;
|
|
392
|
+
}));
|
|
393
|
+
};
|
|
394
|
+
function getPath(graphOrParams, params) {
|
|
395
|
+
if (params === void 0 && typeof graphOrParams === "object" && "target" in graphOrParams) {
|
|
396
|
+
const params2 = graphOrParams;
|
|
397
|
+
return (graph) => getPathImpl(graph, params2);
|
|
398
|
+
} else {
|
|
399
|
+
const graph = graphOrParams;
|
|
400
|
+
return getPathImpl(graph, params);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
var waitForPathImpl = (graph, params, options) => {
|
|
404
|
+
const { timeout = 5e3, interval = 500 } = options ?? {};
|
|
405
|
+
const path = getPathImpl(graph, params);
|
|
406
|
+
if (Option.isSome(path)) {
|
|
407
|
+
return Promise.resolve(path.value);
|
|
408
|
+
}
|
|
409
|
+
const trigger = new Trigger();
|
|
410
|
+
const i = setInterval(() => {
|
|
411
|
+
const path2 = getPathImpl(graph, params);
|
|
412
|
+
if (Option.isSome(path2)) {
|
|
413
|
+
trigger.wake(path2.value);
|
|
112
414
|
}
|
|
415
|
+
}, interval);
|
|
416
|
+
return trigger.wait({
|
|
417
|
+
timeout
|
|
418
|
+
}).finally(() => clearInterval(i));
|
|
419
|
+
};
|
|
420
|
+
function waitForPath(graphOrParams, paramsOrOptions, options) {
|
|
421
|
+
if (typeof graphOrParams === "object" && "target" in graphOrParams) {
|
|
422
|
+
const params = graphOrParams;
|
|
423
|
+
const opts = typeof paramsOrOptions === "object" && !("target" in paramsOrOptions) ? paramsOrOptions : void 0;
|
|
424
|
+
return (graph) => waitForPathImpl(graph, params, opts);
|
|
425
|
+
} else {
|
|
426
|
+
const graph = graphOrParams;
|
|
427
|
+
const params = paramsOrOptions;
|
|
428
|
+
return waitForPathImpl(graph, params, options);
|
|
113
429
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
430
|
+
}
|
|
431
|
+
var initializeImpl = async (graph, id) => {
|
|
432
|
+
const internal = getInternal(graph);
|
|
433
|
+
const initialized = Record.get(internal._initialized, id).pipe(Option.getOrElse(() => false));
|
|
434
|
+
log("initialize", {
|
|
435
|
+
id,
|
|
436
|
+
initialized
|
|
437
|
+
}, {
|
|
438
|
+
F: __dxlog_file,
|
|
439
|
+
L: 661,
|
|
440
|
+
S: void 0,
|
|
441
|
+
C: (f, a) => f(...a)
|
|
442
|
+
});
|
|
443
|
+
if (!initialized) {
|
|
444
|
+
await internal._onInitialize?.(id);
|
|
445
|
+
Record.set(internal._initialized, id, true);
|
|
118
446
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
447
|
+
return graph;
|
|
448
|
+
};
|
|
449
|
+
function initialize(graphOrId, id) {
|
|
450
|
+
if (typeof graphOrId === "string") {
|
|
451
|
+
const id2 = graphOrId;
|
|
452
|
+
return (graph) => initializeImpl(graph, id2);
|
|
453
|
+
} else {
|
|
454
|
+
const graph = graphOrId;
|
|
455
|
+
return initializeImpl(graph, id);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
var expandImpl = (graph, id, relation = "outbound") => {
|
|
459
|
+
const internal = getInternal(graph);
|
|
460
|
+
const key = `${id}$${relation}`;
|
|
461
|
+
const expanded = Record.get(internal._expanded, key).pipe(Option.getOrElse(() => false));
|
|
462
|
+
log("expand", {
|
|
463
|
+
key,
|
|
464
|
+
expanded
|
|
465
|
+
}, {
|
|
466
|
+
F: __dxlog_file,
|
|
467
|
+
L: 702,
|
|
468
|
+
S: void 0,
|
|
469
|
+
C: (f, a) => f(...a)
|
|
470
|
+
});
|
|
471
|
+
if (!expanded) {
|
|
472
|
+
internal._onExpand?.(id, relation);
|
|
473
|
+
Record.set(internal._expanded, key, true);
|
|
474
|
+
}
|
|
475
|
+
return graph;
|
|
476
|
+
};
|
|
477
|
+
function expand(graphOrId, idOrRelation, relation) {
|
|
478
|
+
if (typeof graphOrId === "string") {
|
|
479
|
+
const id = graphOrId;
|
|
480
|
+
const rel = (typeof idOrRelation === "string" ? "outbound" : idOrRelation) ?? "outbound";
|
|
481
|
+
return (graph) => expandImpl(graph, id, rel);
|
|
482
|
+
} else {
|
|
483
|
+
const graph = graphOrId;
|
|
484
|
+
const id = idOrRelation;
|
|
485
|
+
const rel = relation ?? "outbound";
|
|
486
|
+
return expandImpl(graph, id, rel);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
var sortEdgesImpl = (graph, id, relation, order) => {
|
|
490
|
+
const internal = getInternal(graph);
|
|
491
|
+
const edgesAtom = internal._edges(id);
|
|
492
|
+
const edges = internal._registry.get(edgesAtom);
|
|
493
|
+
const unsorted = edges[relation].filter((id2) => !order.includes(id2)) ?? [];
|
|
494
|
+
const sorted = order.filter((id2) => edges[relation].includes(id2)) ?? [];
|
|
495
|
+
edges[relation].splice(0, edges[relation].length, ...[
|
|
496
|
+
...sorted,
|
|
497
|
+
...unsorted
|
|
498
|
+
]);
|
|
499
|
+
internal._registry.set(edgesAtom, edges);
|
|
500
|
+
return graph;
|
|
501
|
+
};
|
|
502
|
+
function sortEdges(graphOrId, idOrRelation, relationOrOrder, order) {
|
|
503
|
+
if (typeof graphOrId === "string") {
|
|
504
|
+
const id = graphOrId;
|
|
505
|
+
const relation = idOrRelation;
|
|
506
|
+
const order2 = relationOrOrder;
|
|
507
|
+
return (graph) => sortEdgesImpl(graph, id, relation, order2);
|
|
508
|
+
} else {
|
|
509
|
+
const graph = graphOrId;
|
|
510
|
+
const id = idOrRelation;
|
|
511
|
+
const relation = relationOrOrder;
|
|
512
|
+
return sortEdgesImpl(graph, id, relation, order);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
var addNodesImpl = (graph, nodes) => {
|
|
516
|
+
Atom2.batch(() => {
|
|
517
|
+
nodes.map((node) => addNodeImpl(graph, node));
|
|
518
|
+
});
|
|
519
|
+
return graph;
|
|
520
|
+
};
|
|
521
|
+
function addNodes(graphOrNodes, nodes) {
|
|
522
|
+
if (nodes === void 0) {
|
|
523
|
+
const nodes2 = graphOrNodes;
|
|
524
|
+
return (graph) => addNodesImpl(graph, nodes2);
|
|
525
|
+
} else {
|
|
526
|
+
const graph = graphOrNodes;
|
|
527
|
+
return addNodesImpl(graph, nodes);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
var addNodeImpl = (graph, nodeArg) => {
|
|
531
|
+
const internal = getInternal(graph);
|
|
532
|
+
const { nodes, edges, id, type, data = null, properties = {}, ...rest } = nodeArg;
|
|
533
|
+
const nodeAtom = internal._node(id);
|
|
534
|
+
const existingNode = internal._registry.get(nodeAtom);
|
|
535
|
+
Option.match(existingNode, {
|
|
536
|
+
onSome: (existing) => {
|
|
537
|
+
const typeChanged = existing.type !== type;
|
|
538
|
+
const dataChanged = existing.data !== data;
|
|
539
|
+
const propertiesChanged = Object.keys(properties).some((key) => existing.properties[key] !== properties[key]);
|
|
540
|
+
log("existing node", {
|
|
541
|
+
id,
|
|
542
|
+
typeChanged,
|
|
543
|
+
dataChanged,
|
|
544
|
+
propertiesChanged
|
|
545
|
+
}, {
|
|
546
|
+
F: __dxlog_file,
|
|
547
|
+
L: 847,
|
|
548
|
+
S: void 0,
|
|
549
|
+
C: (f, a) => f(...a)
|
|
550
|
+
});
|
|
551
|
+
if (typeChanged || dataChanged || propertiesChanged) {
|
|
552
|
+
log("updating node", {
|
|
169
553
|
id,
|
|
170
554
|
type,
|
|
171
555
|
data,
|
|
172
556
|
properties
|
|
173
557
|
}, {
|
|
174
558
|
F: __dxlog_file,
|
|
175
|
-
L:
|
|
176
|
-
S:
|
|
559
|
+
L: 854,
|
|
560
|
+
S: void 0,
|
|
177
561
|
C: (f, a) => f(...a)
|
|
178
562
|
});
|
|
179
|
-
const newNode =
|
|
180
|
-
|
|
563
|
+
const newNode = Option.some({
|
|
564
|
+
...existing,
|
|
565
|
+
...rest,
|
|
181
566
|
type,
|
|
182
567
|
data,
|
|
183
|
-
properties
|
|
568
|
+
properties: {
|
|
569
|
+
...existing.properties,
|
|
570
|
+
...properties
|
|
571
|
+
}
|
|
184
572
|
});
|
|
185
|
-
|
|
186
|
-
|
|
573
|
+
internal._registry.set(nodeAtom, newNode);
|
|
574
|
+
graph.onNodeChanged.emit({
|
|
187
575
|
id,
|
|
188
576
|
node: newNode
|
|
189
577
|
});
|
|
190
578
|
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
this.addEdges(_edges);
|
|
199
|
-
}
|
|
200
|
-
if (edges) {
|
|
201
|
-
todo();
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
removeNodes(ids, edges = false) {
|
|
205
|
-
Rx.batch(() => {
|
|
206
|
-
ids.map((id) => this.removeNode(id, edges));
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
removeNode(id, edges = false) {
|
|
210
|
-
const nodeRx = this._node(id);
|
|
211
|
-
this._registry.set(nodeRx, Option.none());
|
|
212
|
-
this.onNodeChanged.emit({
|
|
213
|
-
id,
|
|
214
|
-
node: Option.none()
|
|
215
|
-
});
|
|
216
|
-
if (edges) {
|
|
217
|
-
const { inbound, outbound } = this._registry.get(this._edges(id));
|
|
218
|
-
const edges2 = [
|
|
219
|
-
...inbound.map((source) => ({
|
|
220
|
-
source,
|
|
221
|
-
target: id
|
|
222
|
-
})),
|
|
223
|
-
...outbound.map((target) => ({
|
|
224
|
-
source: id,
|
|
225
|
-
target
|
|
226
|
-
}))
|
|
227
|
-
];
|
|
228
|
-
this.removeEdges(edges2);
|
|
229
|
-
}
|
|
230
|
-
this._onRemoveNode?.(id);
|
|
231
|
-
}
|
|
232
|
-
addEdges(edges) {
|
|
233
|
-
Rx.batch(() => {
|
|
234
|
-
edges.map((edge) => this.addEdge(edge));
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
addEdge(edgeArg) {
|
|
238
|
-
const sourceRx = this._edges(edgeArg.source);
|
|
239
|
-
const source = this._registry.get(sourceRx);
|
|
240
|
-
if (!source.outbound.includes(edgeArg.target)) {
|
|
241
|
-
log("add outbound edge", {
|
|
242
|
-
source: edgeArg.source,
|
|
243
|
-
target: edgeArg.target
|
|
579
|
+
},
|
|
580
|
+
onNone: () => {
|
|
581
|
+
log("new node", {
|
|
582
|
+
id,
|
|
583
|
+
type,
|
|
584
|
+
data,
|
|
585
|
+
properties
|
|
244
586
|
}, {
|
|
245
587
|
F: __dxlog_file,
|
|
246
|
-
L:
|
|
247
|
-
S:
|
|
588
|
+
L: 867,
|
|
589
|
+
S: void 0,
|
|
248
590
|
C: (f, a) => f(...a)
|
|
249
591
|
});
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
const targetRx = this._edges(edgeArg.target);
|
|
259
|
-
const target = this._registry.get(targetRx);
|
|
260
|
-
if (!target.inbound.includes(edgeArg.source)) {
|
|
261
|
-
log("add inbound edge", {
|
|
262
|
-
source: edgeArg.source,
|
|
263
|
-
target: edgeArg.target
|
|
264
|
-
}, {
|
|
265
|
-
F: __dxlog_file,
|
|
266
|
-
L: 487,
|
|
267
|
-
S: this,
|
|
268
|
-
C: (f, a) => f(...a)
|
|
592
|
+
const newNode = internal._constructNode({
|
|
593
|
+
id,
|
|
594
|
+
type,
|
|
595
|
+
data,
|
|
596
|
+
properties,
|
|
597
|
+
...rest
|
|
269
598
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
],
|
|
275
|
-
outbound: target.outbound
|
|
599
|
+
internal._registry.set(nodeAtom, newNode);
|
|
600
|
+
graph.onNodeChanged.emit({
|
|
601
|
+
id,
|
|
602
|
+
node: newNode
|
|
276
603
|
});
|
|
277
604
|
}
|
|
605
|
+
});
|
|
606
|
+
if (nodes) {
|
|
607
|
+
addNodesImpl(graph, nodes);
|
|
608
|
+
const _edges = nodes.map((node) => ({
|
|
609
|
+
source: id,
|
|
610
|
+
target: node.id
|
|
611
|
+
}));
|
|
612
|
+
addEdgesImpl(graph, _edges);
|
|
278
613
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
edges.map((edge) => this.removeEdge(edge, removeOrphans));
|
|
282
|
-
});
|
|
614
|
+
if (edges) {
|
|
615
|
+
todo();
|
|
283
616
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const targetRx = this._edges(edgeArg.target);
|
|
294
|
-
const target = this._registry.get(targetRx);
|
|
295
|
-
if (target.inbound.includes(edgeArg.source)) {
|
|
296
|
-
this._registry.set(targetRx, {
|
|
297
|
-
inbound: target.inbound.filter((id) => id !== edgeArg.source),
|
|
298
|
-
outbound: target.outbound
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
if (removeOrphans) {
|
|
302
|
-
const source2 = this._registry.get(sourceRx);
|
|
303
|
-
const target2 = this._registry.get(targetRx);
|
|
304
|
-
if (source2.outbound.length === 0 && source2.inbound.length === 0 && edgeArg.source !== ROOT_ID) {
|
|
305
|
-
this.removeNodes([
|
|
306
|
-
edgeArg.source
|
|
307
|
-
]);
|
|
308
|
-
}
|
|
309
|
-
if (target2.outbound.length === 0 && target2.inbound.length === 0 && edgeArg.target !== ROOT_ID) {
|
|
310
|
-
this.removeNodes([
|
|
311
|
-
edgeArg.target
|
|
312
|
-
]);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
617
|
+
return graph;
|
|
618
|
+
};
|
|
619
|
+
function addNode(graphOrNodeArg, nodeArg) {
|
|
620
|
+
if (nodeArg === void 0) {
|
|
621
|
+
const nodeArg2 = graphOrNodeArg;
|
|
622
|
+
return (graph) => addNodeImpl(graph, nodeArg2);
|
|
623
|
+
} else {
|
|
624
|
+
const graph = graphOrNodeArg;
|
|
625
|
+
return addNodeImpl(graph, nodeArg);
|
|
315
626
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
627
|
+
}
|
|
628
|
+
var removeNodesImpl = (graph, ids, edges = false) => {
|
|
629
|
+
Atom2.batch(() => {
|
|
630
|
+
ids.map((id) => removeNodeImpl(graph, id, edges));
|
|
631
|
+
});
|
|
632
|
+
return graph;
|
|
633
|
+
};
|
|
634
|
+
function removeNodes(graphOrIds, idsOrEdges, edges) {
|
|
635
|
+
if (Array.isArray(graphOrIds)) {
|
|
636
|
+
const ids = graphOrIds;
|
|
637
|
+
const edgesArg = typeof idsOrEdges === "boolean" ? idsOrEdges : false;
|
|
638
|
+
return (graph) => removeNodesImpl(graph, ids, edgesArg);
|
|
639
|
+
} else {
|
|
640
|
+
const graph = graphOrIds;
|
|
641
|
+
const ids = idsOrEdges;
|
|
642
|
+
const edgesArg = edges ?? false;
|
|
643
|
+
return removeNodesImpl(graph, ids, edgesArg);
|
|
326
644
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return pipe(this.getNode(source), Option.flatMap((node) => {
|
|
350
|
-
let found = Option.none();
|
|
351
|
-
this.traverse({
|
|
352
|
-
source: node.id,
|
|
353
|
-
visitor: (node2, path) => {
|
|
354
|
-
if (Option.isSome(found)) {
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
if (node2.id === target) {
|
|
358
|
-
found = Option.some(path);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
return found;
|
|
363
|
-
}));
|
|
645
|
+
}
|
|
646
|
+
var removeNodeImpl = (graph, id, edges = false) => {
|
|
647
|
+
const internal = getInternal(graph);
|
|
648
|
+
const nodeAtom = internal._node(id);
|
|
649
|
+
internal._registry.set(nodeAtom, Option.none());
|
|
650
|
+
graph.onNodeChanged.emit({
|
|
651
|
+
id,
|
|
652
|
+
node: Option.none()
|
|
653
|
+
});
|
|
654
|
+
if (edges) {
|
|
655
|
+
const { inbound, outbound } = internal._registry.get(internal._edges(id));
|
|
656
|
+
const edgesToRemove = [
|
|
657
|
+
...inbound.map((source) => ({
|
|
658
|
+
source,
|
|
659
|
+
target: id
|
|
660
|
+
})),
|
|
661
|
+
...outbound.map((target) => ({
|
|
662
|
+
source: id,
|
|
663
|
+
target
|
|
664
|
+
}))
|
|
665
|
+
];
|
|
666
|
+
removeEdgesImpl(graph, edgesToRemove);
|
|
364
667
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
return
|
|
378
|
-
timeout
|
|
379
|
-
}).finally(() => clearInterval(i));
|
|
668
|
+
internal._onRemoveNode?.(id);
|
|
669
|
+
return graph;
|
|
670
|
+
};
|
|
671
|
+
function removeNode(graphOrId, idOrEdges, edges) {
|
|
672
|
+
if (typeof graphOrId === "string") {
|
|
673
|
+
const id = graphOrId;
|
|
674
|
+
const edgesArg = typeof idOrEdges === "boolean" ? idOrEdges : false;
|
|
675
|
+
return (graph) => removeNodeImpl(graph, id, edgesArg);
|
|
676
|
+
} else {
|
|
677
|
+
const graph = graphOrId;
|
|
678
|
+
const id = idOrEdges;
|
|
679
|
+
const edgesArg = edges ?? false;
|
|
680
|
+
return removeNodeImpl(graph, id, edgesArg);
|
|
380
681
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
682
|
+
}
|
|
683
|
+
var addEdgesImpl = (graph, edges) => {
|
|
684
|
+
Atom2.batch(() => {
|
|
685
|
+
edges.map((edge) => addEdgeImpl(graph, edge));
|
|
686
|
+
});
|
|
687
|
+
return graph;
|
|
688
|
+
};
|
|
689
|
+
function addEdges(graphOrEdges, edges) {
|
|
690
|
+
if (edges === void 0) {
|
|
691
|
+
const edges2 = graphOrEdges;
|
|
692
|
+
return (graph) => addEdgesImpl(graph, edges2);
|
|
693
|
+
} else {
|
|
694
|
+
const graph = graphOrEdges;
|
|
695
|
+
return addEdgesImpl(graph, edges);
|
|
389
696
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
697
|
+
}
|
|
698
|
+
var addEdgeImpl = (graph, edgeArg) => {
|
|
699
|
+
const internal = getInternal(graph);
|
|
700
|
+
const sourceAtom = internal._edges(edgeArg.source);
|
|
701
|
+
const source = internal._registry.get(sourceAtom);
|
|
702
|
+
if (!source.outbound.includes(edgeArg.target)) {
|
|
703
|
+
log("add outbound edge", {
|
|
704
|
+
source: edgeArg.source,
|
|
705
|
+
target: edgeArg.target
|
|
706
|
+
}, {
|
|
707
|
+
F: __dxlog_file,
|
|
708
|
+
L: 1026,
|
|
709
|
+
S: void 0,
|
|
710
|
+
C: (f, a) => f(...a)
|
|
711
|
+
});
|
|
712
|
+
internal._registry.set(sourceAtom, {
|
|
713
|
+
inbound: source.inbound,
|
|
714
|
+
outbound: [
|
|
715
|
+
...source.outbound,
|
|
716
|
+
edgeArg.target
|
|
408
717
|
]
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
const targetAtom = internal._edges(edgeArg.target);
|
|
721
|
+
const target = internal._registry.get(targetAtom);
|
|
722
|
+
if (!target.inbound.includes(edgeArg.source)) {
|
|
723
|
+
log("add inbound edge", {
|
|
724
|
+
source: edgeArg.source,
|
|
725
|
+
target: edgeArg.target
|
|
726
|
+
}, {
|
|
727
|
+
F: __dxlog_file,
|
|
728
|
+
L: 1039,
|
|
729
|
+
S: void 0,
|
|
730
|
+
C: (f, a) => f(...a)
|
|
731
|
+
});
|
|
732
|
+
internal._registry.set(targetAtom, {
|
|
733
|
+
inbound: [
|
|
734
|
+
...target.inbound,
|
|
735
|
+
edgeArg.source
|
|
736
|
+
],
|
|
737
|
+
outbound: target.outbound
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
return graph;
|
|
741
|
+
};
|
|
742
|
+
function addEdge(graphOrEdgeArg, edgeArg) {
|
|
743
|
+
if (edgeArg === void 0) {
|
|
744
|
+
const edgeArg2 = graphOrEdgeArg;
|
|
745
|
+
return (graph) => addEdgeImpl(graph, edgeArg2);
|
|
746
|
+
} else {
|
|
747
|
+
const graph = graphOrEdgeArg;
|
|
748
|
+
return addEdgeImpl(graph, edgeArg);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
var removeEdgesImpl = (graph, edges, removeOrphans = false) => {
|
|
752
|
+
Atom2.batch(() => {
|
|
753
|
+
edges.map((edge) => removeEdgeImpl(graph, edge, removeOrphans));
|
|
754
|
+
});
|
|
755
|
+
return graph;
|
|
756
|
+
};
|
|
757
|
+
function removeEdges(graphOrEdges, edgesOrRemoveOrphans, removeOrphans) {
|
|
758
|
+
if (Array.isArray(graphOrEdges)) {
|
|
759
|
+
const edges = graphOrEdges;
|
|
760
|
+
const removeOrphansArg = typeof edgesOrRemoveOrphans === "boolean" ? edgesOrRemoveOrphans : false;
|
|
761
|
+
return (graph) => removeEdgesImpl(graph, edges, removeOrphansArg);
|
|
762
|
+
} else {
|
|
763
|
+
const graph = graphOrEdges;
|
|
764
|
+
const edges = edgesOrRemoveOrphans;
|
|
765
|
+
const removeOrphansArg = removeOrphans ?? false;
|
|
766
|
+
return removeEdgesImpl(graph, edges, removeOrphansArg);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
var removeEdgeImpl = (graph, edgeArg, removeOrphans = false) => {
|
|
770
|
+
const internal = getInternal(graph);
|
|
771
|
+
const sourceAtom = internal._edges(edgeArg.source);
|
|
772
|
+
const source = internal._registry.get(sourceAtom);
|
|
773
|
+
if (source.outbound.includes(edgeArg.target)) {
|
|
774
|
+
internal._registry.set(sourceAtom, {
|
|
775
|
+
inbound: source.inbound,
|
|
776
|
+
outbound: source.outbound.filter((id) => id !== edgeArg.target)
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
const targetAtom = internal._edges(edgeArg.target);
|
|
780
|
+
const target = internal._registry.get(targetAtom);
|
|
781
|
+
if (target.inbound.includes(edgeArg.source)) {
|
|
782
|
+
internal._registry.set(targetAtom, {
|
|
783
|
+
inbound: target.inbound.filter((id) => id !== edgeArg.source),
|
|
784
|
+
outbound: target.outbound
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
if (removeOrphans) {
|
|
788
|
+
const source2 = internal._registry.get(sourceAtom);
|
|
789
|
+
const target2 = internal._registry.get(targetAtom);
|
|
790
|
+
if (source2.outbound.length === 0 && source2.inbound.length === 0 && edgeArg.source !== RootId) {
|
|
791
|
+
removeNodesImpl(graph, [
|
|
792
|
+
edgeArg.source
|
|
793
|
+
]);
|
|
482
794
|
}
|
|
483
|
-
if (
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
795
|
+
if (target2.outbound.length === 0 && target2.inbound.length === 0 && edgeArg.target !== RootId) {
|
|
796
|
+
removeNodesImpl(graph, [
|
|
797
|
+
edgeArg.target
|
|
798
|
+
]);
|
|
487
799
|
}
|
|
488
800
|
}
|
|
801
|
+
return graph;
|
|
802
|
+
};
|
|
803
|
+
function removeEdge(graphOrEdgeArg, edgeArgOrRemoveOrphans, removeOrphans) {
|
|
804
|
+
if (edgeArgOrRemoveOrphans === void 0 || typeof edgeArgOrRemoveOrphans === "boolean" || "source" in graphOrEdgeArg) {
|
|
805
|
+
const edgeArg = graphOrEdgeArg;
|
|
806
|
+
const removeOrphansArg = typeof edgeArgOrRemoveOrphans === "boolean" ? edgeArgOrRemoveOrphans : false;
|
|
807
|
+
return (graph) => removeEdgeImpl(graph, edgeArg, removeOrphansArg);
|
|
808
|
+
} else {
|
|
809
|
+
const graph = graphOrEdgeArg;
|
|
810
|
+
const edgeArg = edgeArgOrRemoveOrphans;
|
|
811
|
+
const removeOrphansArg = removeOrphans ?? false;
|
|
812
|
+
return removeEdgeImpl(graph, edgeArg, removeOrphansArg);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
var make = (params) => {
|
|
816
|
+
return new GraphImpl(params);
|
|
489
817
|
};
|
|
490
818
|
|
|
491
819
|
// src/graph-builder.ts
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
820
|
+
var graph_builder_exports = {};
|
|
821
|
+
__export(graph_builder_exports, {
|
|
822
|
+
GraphBuilderTypeId: () => GraphBuilderTypeId,
|
|
823
|
+
addExtension: () => addExtension,
|
|
824
|
+
createConnector: () => createConnector,
|
|
825
|
+
createExtension: () => createExtension,
|
|
826
|
+
createExtensionRaw: () => createExtensionRaw,
|
|
827
|
+
createTypeExtension: () => createTypeExtension,
|
|
828
|
+
destroy: () => destroy,
|
|
829
|
+
explore: () => explore,
|
|
830
|
+
flattenExtensions: () => flattenExtensions,
|
|
831
|
+
from: () => from,
|
|
832
|
+
make: () => make2,
|
|
833
|
+
removeExtension: () => removeExtension
|
|
834
|
+
});
|
|
835
|
+
import { Atom as Atom3, Registry as Registry2 } from "@effect-atom/atom-react";
|
|
836
|
+
import * as Array2 from "effect/Array";
|
|
837
|
+
import * as Effect from "effect/Effect";
|
|
838
|
+
import * as Function2 from "effect/Function";
|
|
839
|
+
import * as Option3 from "effect/Option";
|
|
840
|
+
import * as Pipeable2 from "effect/Pipeable";
|
|
841
|
+
import * as Record2 from "effect/Record";
|
|
495
842
|
import { log as log2 } from "@dxos/log";
|
|
496
843
|
import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
497
844
|
|
|
498
|
-
// src/node.ts
|
|
499
|
-
var
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
845
|
+
// src/node-matcher.ts
|
|
846
|
+
var node_matcher_exports = {};
|
|
847
|
+
__export(node_matcher_exports, {
|
|
848
|
+
whenAll: () => whenAll,
|
|
849
|
+
whenAny: () => whenAny,
|
|
850
|
+
whenEchoObject: () => whenEchoObject,
|
|
851
|
+
whenEchoObjectMatches: () => whenEchoObjectMatches,
|
|
852
|
+
whenEchoType: () => whenEchoType,
|
|
853
|
+
whenEchoTypeMatches: () => whenEchoTypeMatches,
|
|
854
|
+
whenId: () => whenId,
|
|
855
|
+
whenNodeType: () => whenNodeType,
|
|
856
|
+
whenNot: () => whenNot,
|
|
857
|
+
whenRoot: () => whenRoot
|
|
858
|
+
});
|
|
859
|
+
import * as Option2 from "effect/Option";
|
|
860
|
+
import { Obj } from "@dxos/echo";
|
|
861
|
+
var whenRoot = (node) => node.id === RootId ? Option2.some(node) : Option2.none();
|
|
862
|
+
var whenId = (id) => (node) => node.id === id ? Option2.some(node) : Option2.none();
|
|
863
|
+
var whenNodeType = (type) => (node) => node.type === type ? Option2.some(node) : Option2.none();
|
|
864
|
+
var whenEchoType = (type) => (node) => Obj.instanceOf(type, node.data) ? Option2.some(node.data) : Option2.none();
|
|
865
|
+
var whenEchoObject = (node) => Obj.isObject(node.data) ? Option2.some(node.data) : Option2.none();
|
|
866
|
+
var whenAll = (...matchers) => (node) => {
|
|
867
|
+
for (const matcher of matchers) {
|
|
868
|
+
const result = matcher(node);
|
|
869
|
+
if (Option2.isNone(result)) {
|
|
870
|
+
return Option2.none();
|
|
871
|
+
}
|
|
516
872
|
}
|
|
517
|
-
return
|
|
518
|
-
}
|
|
519
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
520
|
-
var createExtension = (extension) => {
|
|
521
|
-
const { id, position = "static", relation = "outbound", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
522
|
-
const getId = (key) => `${id}/${key}`;
|
|
523
|
-
const resolver = _resolver && Rx2.family((id2) => _resolver(id2).pipe(Rx2.withLabel(`graph-builder:_resolver:${id2}`)));
|
|
524
|
-
const connector = _connector && Rx2.family((node) => _connector(node).pipe(Rx2.withLabel(`graph-builder:_connector:${id}`)));
|
|
525
|
-
const actionGroups = _actionGroups && Rx2.family((node) => _actionGroups(node).pipe(Rx2.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
526
|
-
const actions = _actions && Rx2.family((node) => _actions(node).pipe(Rx2.withLabel(`graph-builder:_actions:${id}`)));
|
|
527
|
-
return [
|
|
528
|
-
resolver ? {
|
|
529
|
-
id: getId("resolver"),
|
|
530
|
-
position,
|
|
531
|
-
resolver
|
|
532
|
-
} : void 0,
|
|
533
|
-
connector ? {
|
|
534
|
-
id: getId("connector"),
|
|
535
|
-
position,
|
|
536
|
-
relation,
|
|
537
|
-
connector: Rx2.family((node) => Rx2.make((get) => {
|
|
538
|
-
try {
|
|
539
|
-
return get(connector(node));
|
|
540
|
-
} catch {
|
|
541
|
-
log2.warn("Error in connector", {
|
|
542
|
-
id: getId("connector"),
|
|
543
|
-
node
|
|
544
|
-
}, {
|
|
545
|
-
F: __dxlog_file2,
|
|
546
|
-
L: 109,
|
|
547
|
-
S: void 0,
|
|
548
|
-
C: (f, a) => f(...a)
|
|
549
|
-
});
|
|
550
|
-
return [];
|
|
551
|
-
}
|
|
552
|
-
}).pipe(Rx2.withLabel(`graph-builder:connector:${id}`)))
|
|
553
|
-
} : void 0,
|
|
554
|
-
actionGroups ? {
|
|
555
|
-
id: getId("actionGroups"),
|
|
556
|
-
position,
|
|
557
|
-
relation: "outbound",
|
|
558
|
-
connector: Rx2.family((node) => Rx2.make((get) => {
|
|
559
|
-
try {
|
|
560
|
-
return get(actionGroups(node)).map((arg) => ({
|
|
561
|
-
...arg,
|
|
562
|
-
data: actionGroupSymbol,
|
|
563
|
-
type: ACTION_GROUP_TYPE
|
|
564
|
-
}));
|
|
565
|
-
} catch {
|
|
566
|
-
log2.warn("Error in actionGroups", {
|
|
567
|
-
id: getId("actionGroups"),
|
|
568
|
-
node
|
|
569
|
-
}, {
|
|
570
|
-
F: __dxlog_file2,
|
|
571
|
-
L: 130,
|
|
572
|
-
S: void 0,
|
|
573
|
-
C: (f, a) => f(...a)
|
|
574
|
-
});
|
|
575
|
-
return [];
|
|
576
|
-
}
|
|
577
|
-
}).pipe(Rx2.withLabel(`graph-builder:connector:actionGroups:${id}`)))
|
|
578
|
-
} : void 0,
|
|
579
|
-
actions ? {
|
|
580
|
-
id: getId("actions"),
|
|
581
|
-
position,
|
|
582
|
-
relation: "outbound",
|
|
583
|
-
connector: Rx2.family((node) => Rx2.make((get) => {
|
|
584
|
-
try {
|
|
585
|
-
return get(actions(node)).map((arg) => ({
|
|
586
|
-
...arg,
|
|
587
|
-
type: ACTION_TYPE
|
|
588
|
-
}));
|
|
589
|
-
} catch {
|
|
590
|
-
log2.warn("Error in actions", {
|
|
591
|
-
id: getId("actions"),
|
|
592
|
-
node
|
|
593
|
-
}, {
|
|
594
|
-
F: __dxlog_file2,
|
|
595
|
-
L: 147,
|
|
596
|
-
S: void 0,
|
|
597
|
-
C: (f, a) => f(...a)
|
|
598
|
-
});
|
|
599
|
-
return [];
|
|
600
|
-
}
|
|
601
|
-
}).pipe(Rx2.withLabel(`graph-builder:connector:actions:${id}`)))
|
|
602
|
-
} : void 0
|
|
603
|
-
].filter(isNonNullable2);
|
|
873
|
+
return Option2.some(node);
|
|
604
874
|
};
|
|
605
|
-
var
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
} else {
|
|
612
|
-
return [
|
|
613
|
-
...acc,
|
|
614
|
-
extension
|
|
615
|
-
];
|
|
875
|
+
var whenAny = (...matchers) => (node) => {
|
|
876
|
+
for (const matcher of matchers) {
|
|
877
|
+
const result = matcher(node);
|
|
878
|
+
if (Option2.isSome(result)) {
|
|
879
|
+
return Option2.some(node);
|
|
880
|
+
}
|
|
616
881
|
}
|
|
882
|
+
return Option2.none();
|
|
617
883
|
};
|
|
618
|
-
var
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
884
|
+
var whenEchoTypeMatches = (type) => (node) => Obj.instanceOf(type, node.data) ? Option2.some(node) : Option2.none();
|
|
885
|
+
var whenEchoObjectMatches = (node) => Obj.isObject(node.data) ? Option2.some(node) : Option2.none();
|
|
886
|
+
var whenNot = (matcher) => (node) => Option2.isNone(matcher(node)) ? Option2.some(node) : Option2.none();
|
|
887
|
+
|
|
888
|
+
// src/graph-builder.ts
|
|
889
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
890
|
+
var GraphBuilderTypeId = Symbol.for("@dxos/app-graph/GraphBuilder");
|
|
891
|
+
var GraphBuilderImpl = class {
|
|
892
|
+
[GraphBuilderTypeId] = GraphBuilderTypeId;
|
|
893
|
+
pipe() {
|
|
894
|
+
return Pipeable2.pipeArguments(this, arguments);
|
|
895
|
+
}
|
|
896
|
+
// TODO(wittjosiah): Use Context.
|
|
897
|
+
_subscriptions = /* @__PURE__ */ new Map();
|
|
898
|
+
_extensions = Atom3.make(Record2.empty()).pipe(Atom3.keepAlive, Atom3.withLabel("graph-builder:extensions"));
|
|
899
|
+
_initialized = {};
|
|
900
|
+
_registry;
|
|
901
|
+
_graph;
|
|
902
|
+
constructor({ registry, ...params } = {}) {
|
|
903
|
+
this._registry = registry ?? Registry2.make();
|
|
904
|
+
const graph = make({
|
|
905
|
+
...params,
|
|
906
|
+
registry: this._registry,
|
|
907
|
+
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
908
|
+
onInitialize: (id) => this._onInitialize(id),
|
|
909
|
+
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
630
910
|
});
|
|
911
|
+
this._graph = graph;
|
|
631
912
|
}
|
|
632
913
|
get graph() {
|
|
633
914
|
return this._graph;
|
|
@@ -635,56 +916,27 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
635
916
|
get extensions() {
|
|
636
917
|
return this._extensions;
|
|
637
918
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
this._registry.set(this._extensions, Record2.set(extensions2, extension.id, extension));
|
|
919
|
+
_resolvers = Atom3.family((id) => {
|
|
920
|
+
return Atom3.make((get2) => {
|
|
921
|
+
return Function2.pipe(get2(this._extensions), Record2.values, Array2.sortBy(byPosition), Array2.map(({ resolver }) => resolver), Array2.filter(isNonNullable2), Array2.map((resolver) => get2(resolver(id))), Array2.filter(isNonNullable2), Array2.head);
|
|
642
922
|
});
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
...path,
|
|
661
|
-
node.id
|
|
662
|
-
]);
|
|
663
|
-
if (shouldContinue === false) {
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
const nodes = Object.values(this._registry.get(this._extensions)).filter((extension) => relation === (extension.relation ?? "outbound")).map((extension) => extension.connector).filter(isNonNullable2).flatMap((connector) => registry.get(connector(this._graph.node(source))));
|
|
667
|
-
await Promise.all(nodes.map((nodeArg) => {
|
|
668
|
-
registry.set(this._graph._node(nodeArg.id), this._graph._constructNode(nodeArg));
|
|
669
|
-
return this.explore({
|
|
670
|
-
registry,
|
|
671
|
-
source: nodeArg.id,
|
|
672
|
-
relation,
|
|
673
|
-
visitor
|
|
674
|
-
}, [
|
|
675
|
-
...path,
|
|
676
|
-
node.id
|
|
677
|
-
]);
|
|
678
|
-
}));
|
|
679
|
-
if (registry !== this._registry) {
|
|
680
|
-
registry.reset();
|
|
681
|
-
registry.dispose();
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
destroy() {
|
|
685
|
-
this._subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
686
|
-
this._subscriptions.clear();
|
|
687
|
-
}
|
|
923
|
+
});
|
|
924
|
+
_connectors = Atom3.family((key) => {
|
|
925
|
+
return Atom3.make((get2) => {
|
|
926
|
+
const [id, relation] = key.split("+");
|
|
927
|
+
const node = this._graph.node(id);
|
|
928
|
+
return Function2.pipe(
|
|
929
|
+
get2(this._extensions),
|
|
930
|
+
Record2.values,
|
|
931
|
+
// TODO(wittjosiah): Sort on write rather than read.
|
|
932
|
+
Array2.sortBy(byPosition),
|
|
933
|
+
Array2.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
934
|
+
Array2.map(({ connector }) => connector?.(node)),
|
|
935
|
+
Array2.filter(isNonNullable2),
|
|
936
|
+
Array2.flatMap((result) => get2(result))
|
|
937
|
+
);
|
|
938
|
+
}).pipe(Atom3.withLabel(`graph-builder:connectors:${key}`));
|
|
939
|
+
});
|
|
688
940
|
_onExpand(id, relation) {
|
|
689
941
|
log2("onExpand", {
|
|
690
942
|
id,
|
|
@@ -692,7 +944,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
692
944
|
registry: getDebugName(this._registry)
|
|
693
945
|
}, {
|
|
694
946
|
F: __dxlog_file2,
|
|
695
|
-
L:
|
|
947
|
+
L: 176,
|
|
696
948
|
S: this,
|
|
697
949
|
C: (f, a) => f(...a)
|
|
698
950
|
});
|
|
@@ -709,25 +961,25 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
709
961
|
removed
|
|
710
962
|
}, {
|
|
711
963
|
F: __dxlog_file2,
|
|
712
|
-
L:
|
|
964
|
+
L: 187,
|
|
713
965
|
S: this,
|
|
714
966
|
C: (f, a) => f(...a)
|
|
715
967
|
});
|
|
716
968
|
const update = () => {
|
|
717
|
-
|
|
718
|
-
this._graph
|
|
969
|
+
Atom3.batch(() => {
|
|
970
|
+
removeEdges(this._graph, removed.map((target) => ({
|
|
719
971
|
source: id,
|
|
720
972
|
target
|
|
721
973
|
})), true);
|
|
722
|
-
this._graph
|
|
723
|
-
this._graph
|
|
974
|
+
addNodes(this._graph, nodes);
|
|
975
|
+
addEdges(this._graph, nodes.map((node) => relation === "outbound" ? {
|
|
724
976
|
source: id,
|
|
725
977
|
target: node.id
|
|
726
978
|
} : {
|
|
727
979
|
source: node.id,
|
|
728
980
|
target: id
|
|
729
981
|
}));
|
|
730
|
-
this._graph
|
|
982
|
+
sortEdges(this._graph, id, relation, nodes.map(({ id: id2 }) => id2));
|
|
731
983
|
});
|
|
732
984
|
};
|
|
733
985
|
if (typeof requestAnimationFrame === "function") {
|
|
@@ -746,23 +998,23 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
746
998
|
id
|
|
747
999
|
}, {
|
|
748
1000
|
F: __dxlog_file2,
|
|
749
|
-
L:
|
|
1001
|
+
L: 227,
|
|
750
1002
|
S: this,
|
|
751
1003
|
C: (f, a) => f(...a)
|
|
752
1004
|
});
|
|
753
1005
|
const resolver = this._resolvers(id);
|
|
754
1006
|
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
755
1007
|
const trigger = this._initialized[id];
|
|
756
|
-
|
|
1008
|
+
Option3.match(node, {
|
|
757
1009
|
onSome: (node2) => {
|
|
758
|
-
this._graph
|
|
1010
|
+
addNodes(this._graph, [
|
|
759
1011
|
node2
|
|
760
1012
|
]);
|
|
761
1013
|
trigger?.wake();
|
|
762
1014
|
},
|
|
763
1015
|
onNone: () => {
|
|
764
1016
|
trigger?.wake();
|
|
765
|
-
this._graph
|
|
1017
|
+
removeNodes(this._graph, [
|
|
766
1018
|
id
|
|
767
1019
|
]);
|
|
768
1020
|
}
|
|
@@ -776,78 +1028,270 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
776
1028
|
this._subscriptions.get(id)?.();
|
|
777
1029
|
this._subscriptions.delete(id);
|
|
778
1030
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
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);
|
|
788
|
-
});
|
|
789
|
-
}));
|
|
790
|
-
_define_property2(this, "_connectors", Rx2.family((key) => {
|
|
791
|
-
return Rx2.make((get) => {
|
|
792
|
-
const [id, relation] = key.split("+");
|
|
793
|
-
const node = this._graph.node(id);
|
|
794
|
-
return pipe2(
|
|
795
|
-
get(this._extensions),
|
|
796
|
-
Record2.values,
|
|
797
|
-
// TODO(wittjosiah): Sort on write rather than read.
|
|
798
|
-
Array.sortBy(byPosition),
|
|
799
|
-
Array.filter(({ relation: _relation = "outbound" }) => _relation === relation),
|
|
800
|
-
Array.map(({ connector }) => connector?.(node)),
|
|
801
|
-
Array.filter(isNonNullable2),
|
|
802
|
-
Array.flatMap((result) => get(result))
|
|
803
|
-
);
|
|
804
|
-
}).pipe(Rx2.withLabel(`graph-builder:connectors:${key}`));
|
|
805
|
-
}));
|
|
806
|
-
this._registry = registry ?? Registry2.make();
|
|
807
|
-
this._graph = new Graph({
|
|
808
|
-
...params,
|
|
809
|
-
registry: this._registry,
|
|
810
|
-
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
811
|
-
onInitialize: (id) => this._onInitialize(id),
|
|
812
|
-
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
1031
|
+
};
|
|
1032
|
+
var make2 = (params) => {
|
|
1033
|
+
return new GraphBuilderImpl(params);
|
|
1034
|
+
};
|
|
1035
|
+
var from = (pickle, registry) => {
|
|
1036
|
+
if (!pickle) {
|
|
1037
|
+
return make2({
|
|
1038
|
+
registry
|
|
813
1039
|
});
|
|
814
1040
|
}
|
|
1041
|
+
const { nodes, edges } = JSON.parse(pickle);
|
|
1042
|
+
return make2({
|
|
1043
|
+
nodes,
|
|
1044
|
+
edges,
|
|
1045
|
+
registry
|
|
1046
|
+
});
|
|
815
1047
|
};
|
|
816
|
-
var
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
get.addFinalizer(() => dispose());
|
|
822
|
-
return cb();
|
|
1048
|
+
var addExtensionImpl = (builder, extensions) => {
|
|
1049
|
+
const internal = builder;
|
|
1050
|
+
flattenExtensions(extensions).forEach((extension) => {
|
|
1051
|
+
const extensions2 = internal._registry.get(internal._extensions);
|
|
1052
|
+
internal._registry.set(internal._extensions, Record2.set(extensions2, extension.id, extension));
|
|
823
1053
|
});
|
|
1054
|
+
return builder;
|
|
824
1055
|
};
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
1056
|
+
function addExtension(builderOrExtensions, extensions) {
|
|
1057
|
+
if (extensions === void 0) {
|
|
1058
|
+
const extensions2 = builderOrExtensions;
|
|
1059
|
+
return (builder) => addExtensionImpl(builder, extensions2);
|
|
1060
|
+
} else {
|
|
1061
|
+
const builder = builderOrExtensions;
|
|
1062
|
+
return addExtensionImpl(builder, extensions);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
var removeExtensionImpl = (builder, id) => {
|
|
1066
|
+
const internal = builder;
|
|
1067
|
+
const extensions = internal._registry.get(internal._extensions);
|
|
1068
|
+
internal._registry.set(internal._extensions, Record2.remove(extensions, id));
|
|
1069
|
+
return builder;
|
|
1070
|
+
};
|
|
1071
|
+
function removeExtension(builderOrId, id) {
|
|
1072
|
+
if (typeof builderOrId === "string") {
|
|
1073
|
+
const id2 = builderOrId;
|
|
1074
|
+
return (builder) => removeExtensionImpl(builder, id2);
|
|
1075
|
+
} else {
|
|
1076
|
+
const builder = builderOrId;
|
|
1077
|
+
return removeExtensionImpl(builder, id);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
var exploreImpl = async (builder, options, path = []) => {
|
|
1081
|
+
const internal = builder;
|
|
1082
|
+
const { registry = Registry2.make(), source = RootId, relation = "outbound", visitor } = options;
|
|
1083
|
+
if (path.includes(source)) {
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
if (!isNode()) {
|
|
1087
|
+
const { yieldOrContinue } = await import("main-thread-scheduling");
|
|
1088
|
+
await yieldOrContinue("idle");
|
|
1089
|
+
}
|
|
1090
|
+
const node = registry.get(internal._graph.nodeOrThrow(source));
|
|
1091
|
+
const shouldContinue = await visitor(node, [
|
|
1092
|
+
...path,
|
|
1093
|
+
node.id
|
|
1094
|
+
]);
|
|
1095
|
+
if (shouldContinue === false) {
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
const nodes = Object.values(internal._registry.get(internal._extensions)).filter((extension) => relation === (extension.relation ?? "outbound")).map((extension) => extension.connector).filter(isNonNullable2).flatMap((connector) => registry.get(connector(internal._graph.node(source))));
|
|
1099
|
+
await Promise.all(nodes.map((nodeArg) => {
|
|
1100
|
+
registry.set(internal._graph._node(nodeArg.id), internal._graph._constructNode(nodeArg));
|
|
1101
|
+
return exploreImpl(builder, {
|
|
1102
|
+
registry,
|
|
1103
|
+
source: nodeArg.id,
|
|
1104
|
+
relation,
|
|
1105
|
+
visitor
|
|
1106
|
+
}, [
|
|
1107
|
+
...path,
|
|
1108
|
+
node.id
|
|
1109
|
+
]);
|
|
1110
|
+
}));
|
|
1111
|
+
if (registry !== internal._registry) {
|
|
1112
|
+
registry.reset();
|
|
1113
|
+
registry.dispose();
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
function explore(builderOrOptions, optionsOrPath, path) {
|
|
1117
|
+
if (typeof builderOrOptions === "object" && "visitor" in builderOrOptions) {
|
|
1118
|
+
const options = builderOrOptions;
|
|
1119
|
+
const path2 = Array2.isArray(optionsOrPath) ? optionsOrPath : void 0;
|
|
1120
|
+
return (builder) => exploreImpl(builder, options, path2);
|
|
1121
|
+
} else {
|
|
1122
|
+
const builder = builderOrOptions;
|
|
1123
|
+
const options = optionsOrPath;
|
|
1124
|
+
const pathArg = path ?? (Array2.isArray(optionsOrPath) ? optionsOrPath : void 0);
|
|
1125
|
+
return exploreImpl(builder, options, pathArg);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
var destroyImpl = (builder) => {
|
|
1129
|
+
const internal = builder;
|
|
1130
|
+
internal._subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
1131
|
+
internal._subscriptions.clear();
|
|
1132
|
+
};
|
|
1133
|
+
function destroy(builder) {
|
|
1134
|
+
if (builder === void 0) {
|
|
1135
|
+
return (builder2) => destroyImpl(builder2);
|
|
1136
|
+
} else {
|
|
1137
|
+
return destroyImpl(builder);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
var createExtensionRaw = (extension) => {
|
|
1141
|
+
const { id, position = "static", relation = "outbound", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
1142
|
+
const getId = (key) => `${id}/${key}`;
|
|
1143
|
+
const resolver = _resolver && Atom3.family((id2) => _resolver(id2).pipe(Atom3.withLabel(`graph-builder:_resolver:${id2}`)));
|
|
1144
|
+
const connector = _connector && Atom3.family((node) => _connector(node).pipe(Atom3.withLabel(`graph-builder:_connector:${id}`)));
|
|
1145
|
+
const actionGroups = _actionGroups && Atom3.family((node) => _actionGroups(node).pipe(Atom3.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
1146
|
+
const actions = _actions && Atom3.family((node) => _actions(node).pipe(Atom3.withLabel(`graph-builder:_actions:${id}`)));
|
|
1147
|
+
return [
|
|
1148
|
+
resolver ? {
|
|
1149
|
+
id: getId("resolver"),
|
|
1150
|
+
position,
|
|
1151
|
+
resolver
|
|
1152
|
+
} : void 0,
|
|
1153
|
+
connector ? {
|
|
1154
|
+
id: getId("connector"),
|
|
1155
|
+
position,
|
|
1156
|
+
relation,
|
|
1157
|
+
connector: Atom3.family((node) => Atom3.make((get2) => {
|
|
1158
|
+
try {
|
|
1159
|
+
return get2(connector(node));
|
|
1160
|
+
} catch (error) {
|
|
1161
|
+
log2.warn("Error in connector", {
|
|
1162
|
+
id: getId("connector"),
|
|
1163
|
+
node,
|
|
1164
|
+
error
|
|
1165
|
+
}, {
|
|
1166
|
+
F: __dxlog_file2,
|
|
1167
|
+
L: 509,
|
|
1168
|
+
S: void 0,
|
|
1169
|
+
C: (f, a) => f(...a)
|
|
1170
|
+
});
|
|
1171
|
+
return [];
|
|
1172
|
+
}
|
|
1173
|
+
}).pipe(Atom3.withLabel(`graph-builder:connector:${id}`)))
|
|
1174
|
+
} : void 0,
|
|
1175
|
+
actionGroups ? {
|
|
1176
|
+
id: getId("actionGroups"),
|
|
1177
|
+
position,
|
|
1178
|
+
relation: "outbound",
|
|
1179
|
+
connector: Atom3.family((node) => Atom3.make((get2) => {
|
|
1180
|
+
try {
|
|
1181
|
+
return get2(actionGroups(node)).map((arg) => ({
|
|
1182
|
+
...arg,
|
|
1183
|
+
data: actionGroupSymbol,
|
|
1184
|
+
type: ActionGroupType
|
|
1185
|
+
}));
|
|
1186
|
+
} catch (error) {
|
|
1187
|
+
log2.warn("Error in actionGroups", {
|
|
1188
|
+
id: getId("actionGroups"),
|
|
1189
|
+
node,
|
|
1190
|
+
error
|
|
1191
|
+
}, {
|
|
1192
|
+
F: __dxlog_file2,
|
|
1193
|
+
L: 530,
|
|
1194
|
+
S: void 0,
|
|
1195
|
+
C: (f, a) => f(...a)
|
|
1196
|
+
});
|
|
1197
|
+
return [];
|
|
1198
|
+
}
|
|
1199
|
+
}).pipe(Atom3.withLabel(`graph-builder:connector:actionGroups:${id}`)))
|
|
1200
|
+
} : void 0,
|
|
1201
|
+
actions ? {
|
|
1202
|
+
id: getId("actions"),
|
|
1203
|
+
position,
|
|
1204
|
+
relation: "outbound",
|
|
1205
|
+
connector: Atom3.family((node) => Atom3.make((get2) => {
|
|
1206
|
+
try {
|
|
1207
|
+
return get2(actions(node)).map((arg) => ({
|
|
1208
|
+
...arg,
|
|
1209
|
+
type: ActionType
|
|
1210
|
+
}));
|
|
1211
|
+
} catch (error) {
|
|
1212
|
+
log2.warn("Error in actions", {
|
|
1213
|
+
id: getId("actions"),
|
|
1214
|
+
node,
|
|
1215
|
+
error
|
|
1216
|
+
}, {
|
|
1217
|
+
F: __dxlog_file2,
|
|
1218
|
+
L: 547,
|
|
1219
|
+
S: void 0,
|
|
1220
|
+
C: (f, a) => f(...a)
|
|
1221
|
+
});
|
|
1222
|
+
return [];
|
|
1223
|
+
}
|
|
1224
|
+
}).pipe(Atom3.withLabel(`graph-builder:connector:actions:${id}`)))
|
|
1225
|
+
} : void 0
|
|
1226
|
+
].filter(isNonNullable2);
|
|
1227
|
+
};
|
|
1228
|
+
var runEffectSyncWithFallback = (effect, context2, extensionId, fallback) => {
|
|
1229
|
+
return Effect.runSync(effect.pipe(Effect.provide(context2), Effect.catchAll((error) => {
|
|
1230
|
+
log2.warn("Extension failed", {
|
|
1231
|
+
extension: extensionId,
|
|
1232
|
+
error
|
|
1233
|
+
}, {
|
|
1234
|
+
F: __dxlog_file2,
|
|
1235
|
+
L: 590,
|
|
1236
|
+
S: void 0,
|
|
1237
|
+
C: (f, a) => f(...a)
|
|
1238
|
+
});
|
|
1239
|
+
return Effect.succeed(fallback);
|
|
1240
|
+
})));
|
|
1241
|
+
};
|
|
1242
|
+
var createExtension = (options) => Effect.map(Effect.context(), (context2) => {
|
|
1243
|
+
const { id, match: match3, actions, connector, resolver, relation, position } = options;
|
|
1244
|
+
const connectorExtension = connector ? createConnectorWithRuntime(id, match3, connector, context2) : void 0;
|
|
1245
|
+
const actionsExtension = actions ? (node) => Atom3.make((get2) => Function2.pipe(get2(node), Option3.flatMap(match3), Option3.map((matched) => runEffectSyncWithFallback(actions(matched, get2), context2, id, []).map((action) => ({
|
|
1246
|
+
...action,
|
|
1247
|
+
// Attach captured context for action execution.
|
|
1248
|
+
_actionContext: context2
|
|
1249
|
+
}))), Option3.getOrElse(() => []))) : void 0;
|
|
1250
|
+
const resolverExtension = resolver ? (nodeId) => Atom3.make((get2) => runEffectSyncWithFallback(resolver(nodeId, get2), context2, id, null) ?? null) : void 0;
|
|
1251
|
+
return createExtensionRaw({
|
|
1252
|
+
id,
|
|
1253
|
+
relation,
|
|
1254
|
+
position,
|
|
1255
|
+
connector: connectorExtension,
|
|
1256
|
+
actions: actionsExtension,
|
|
1257
|
+
resolver: resolverExtension
|
|
830
1258
|
});
|
|
831
1259
|
});
|
|
832
|
-
var
|
|
833
|
-
return
|
|
1260
|
+
var createConnector = (matcher, factory) => {
|
|
1261
|
+
return (node) => Atom3.make((get2) => Function2.pipe(get2(node), Option3.flatMap(matcher), Option3.map((data) => factory(data, get2)), Option3.getOrElse(() => [])));
|
|
1262
|
+
};
|
|
1263
|
+
var createConnectorWithRuntime = (extensionId, matcher, factory, context2) => {
|
|
1264
|
+
return (node) => Atom3.make((get2) => Function2.pipe(get2(node), Option3.flatMap(matcher), Option3.map((data) => runEffectSyncWithFallback(factory(data, get2), context2, extensionId, [])), Option3.getOrElse(() => [])));
|
|
1265
|
+
};
|
|
1266
|
+
var createTypeExtension = (options) => {
|
|
1267
|
+
const { id, type, actions, connector, relation, position } = options;
|
|
1268
|
+
return createExtension({
|
|
1269
|
+
id,
|
|
1270
|
+
match: whenEchoType(type),
|
|
1271
|
+
actions,
|
|
1272
|
+
connector,
|
|
1273
|
+
relation,
|
|
1274
|
+
position
|
|
1275
|
+
});
|
|
1276
|
+
};
|
|
1277
|
+
var flattenExtensions = (extension, acc = []) => {
|
|
1278
|
+
if (Array2.isArray(extension)) {
|
|
1279
|
+
return [
|
|
1280
|
+
...acc,
|
|
1281
|
+
...extension.flatMap((ext) => flattenExtensions(ext, acc))
|
|
1282
|
+
];
|
|
1283
|
+
} else {
|
|
1284
|
+
return [
|
|
1285
|
+
...acc,
|
|
1286
|
+
extension
|
|
1287
|
+
];
|
|
1288
|
+
}
|
|
834
1289
|
};
|
|
835
1290
|
export {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
ROOT_TYPE,
|
|
842
|
-
actionGroupSymbol,
|
|
843
|
-
createExtension,
|
|
844
|
-
flattenExtensions,
|
|
845
|
-
getGraph,
|
|
846
|
-
isAction,
|
|
847
|
-
isActionGroup,
|
|
848
|
-
isActionLike,
|
|
849
|
-
isGraphNode,
|
|
850
|
-
rxFromObservable,
|
|
851
|
-
rxFromSignal
|
|
1291
|
+
atoms_exports as CreateAtom,
|
|
1292
|
+
graph_exports as Graph,
|
|
1293
|
+
graph_builder_exports as GraphBuilder,
|
|
1294
|
+
node_exports as Node,
|
|
1295
|
+
node_matcher_exports as NodeMatcher
|
|
852
1296
|
};
|
|
853
1297
|
//# sourceMappingURL=index.mjs.map
|