@dxos/app-graph 0.8.4-main.72ec0f3 → 0.8.4-main.8342792842
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 +1012 -551
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1011 -551
- 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 +107 -65
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +174 -204
- 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.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -33
- package/src/atoms.ts +25 -0
- package/src/graph-builder.test.ts +494 -78
- package/src/graph-builder.ts +543 -250
- package/src/graph.test.ts +297 -104
- package/src/graph.ts +934 -404
- 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 +94 -92
- package/src/stories/Tree.tsx +1 -1
- 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 -219
- package/src/testing.ts +0 -20
|
@@ -1,20 +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
|
-
|
|
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";
|
|
3
54
|
import * as Function from "effect/Function";
|
|
4
55
|
import * as Option from "effect/Option";
|
|
56
|
+
import * as Pipeable from "effect/Pipeable";
|
|
5
57
|
import * as Record from "effect/Record";
|
|
6
58
|
import { Event, Trigger } from "@dxos/async";
|
|
7
59
|
import { todo } from "@dxos/debug";
|
|
8
60
|
import { invariant } from "@dxos/invariant";
|
|
9
61
|
import { log } from "@dxos/log";
|
|
10
62
|
import { isNonNullable } from "@dxos/util";
|
|
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
|
|
11
88
|
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
12
89
|
var graphSymbol = Symbol("graph");
|
|
13
90
|
var getGraph = (node) => {
|
|
14
91
|
const graph = node[graphSymbol];
|
|
15
92
|
invariant(graph, "Node is not associated with a graph.", {
|
|
16
93
|
F: __dxlog_file,
|
|
17
|
-
L:
|
|
94
|
+
L: 32,
|
|
18
95
|
S: void 0,
|
|
19
96
|
A: [
|
|
20
97
|
"graph",
|
|
@@ -23,11 +100,14 @@ var getGraph = (node) => {
|
|
|
23
100
|
});
|
|
24
101
|
return graph;
|
|
25
102
|
};
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
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);
|
|
110
|
+
}
|
|
31
111
|
onNodeChanged = new Event();
|
|
32
112
|
_onExpand;
|
|
33
113
|
_onInitialize;
|
|
@@ -38,26 +118,26 @@ var Graph = class {
|
|
|
38
118
|
_initialEdges = Record.empty();
|
|
39
119
|
_initialNodes = Record.fromEntries([
|
|
40
120
|
[
|
|
41
|
-
|
|
121
|
+
RootId,
|
|
42
122
|
this._constructNode({
|
|
43
|
-
id:
|
|
44
|
-
type:
|
|
123
|
+
id: RootId,
|
|
124
|
+
type: RootType,
|
|
45
125
|
data: null,
|
|
46
126
|
properties: {}
|
|
47
127
|
})
|
|
48
128
|
]
|
|
49
129
|
]);
|
|
50
130
|
/** @internal */
|
|
51
|
-
_node =
|
|
131
|
+
_node = Atom2.family((id) => {
|
|
52
132
|
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
53
|
-
return
|
|
133
|
+
return Atom2.make(initial).pipe(Atom2.keepAlive, Atom2.withLabel(`graph:node:${id}`));
|
|
54
134
|
});
|
|
55
|
-
_nodeOrThrow =
|
|
56
|
-
return
|
|
135
|
+
_nodeOrThrow = Atom2.family((id) => {
|
|
136
|
+
return Atom2.make((get2) => {
|
|
57
137
|
const node = get2(this._node(id));
|
|
58
138
|
invariant(Option.isSome(node), `Node not available: ${id}`, {
|
|
59
139
|
F: __dxlog_file,
|
|
60
|
-
L:
|
|
140
|
+
L: 174,
|
|
61
141
|
S: this,
|
|
62
142
|
A: [
|
|
63
143
|
"Option.isSome(node)",
|
|
@@ -67,31 +147,31 @@ var Graph = class {
|
|
|
67
147
|
return node.value;
|
|
68
148
|
});
|
|
69
149
|
});
|
|
70
|
-
_edges =
|
|
150
|
+
_edges = Atom2.family((id) => {
|
|
71
151
|
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
72
152
|
inbound: [],
|
|
73
153
|
outbound: []
|
|
74
154
|
})));
|
|
75
|
-
return
|
|
155
|
+
return Atom2.make(initial).pipe(Atom2.keepAlive, Atom2.withLabel(`graph:edges:${id}`));
|
|
76
156
|
});
|
|
77
157
|
// NOTE: Currently the argument to the family needs to be referentially stable for the atom to be referentially stable.
|
|
78
158
|
// TODO(wittjosiah): Atom feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
79
|
-
_connections =
|
|
80
|
-
return
|
|
159
|
+
_connections = Atom2.family((key) => {
|
|
160
|
+
return Atom2.make((get2) => {
|
|
81
161
|
const [id, relation] = key.split("$");
|
|
82
162
|
const edges = get2(this._edges(id));
|
|
83
163
|
return edges[relation].map((id2) => get2(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
84
|
-
}).pipe(
|
|
164
|
+
}).pipe(Atom2.withLabel(`graph:connections:${key}`));
|
|
85
165
|
});
|
|
86
|
-
_actions =
|
|
87
|
-
return
|
|
88
|
-
return get2(this._connections(`${id}$outbound`)).filter((node) => node.type ===
|
|
89
|
-
}).pipe(
|
|
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}`));
|
|
90
170
|
});
|
|
91
|
-
_json =
|
|
92
|
-
return
|
|
93
|
-
const
|
|
94
|
-
const nodes = get2(this.
|
|
171
|
+
_json = Atom2.family((id) => {
|
|
172
|
+
return Atom2.make((get2) => {
|
|
173
|
+
const toJSON2 = (node, seen = []) => {
|
|
174
|
+
const nodes = get2(this._connections(`${node.id}$outbound`));
|
|
95
175
|
const obj = {
|
|
96
176
|
id: node.id,
|
|
97
177
|
type: node.type
|
|
@@ -105,14 +185,14 @@ var Graph = class {
|
|
|
105
185
|
...seen,
|
|
106
186
|
node.id
|
|
107
187
|
];
|
|
108
|
-
return nextSeen.includes(n.id) ? void 0 :
|
|
188
|
+
return nextSeen.includes(n.id) ? void 0 : toJSON2(n, nextSeen);
|
|
109
189
|
}).filter(isNonNullable);
|
|
110
190
|
}
|
|
111
191
|
return obj;
|
|
112
192
|
};
|
|
113
|
-
const root = get2(this.
|
|
114
|
-
return
|
|
115
|
-
}).pipe(
|
|
193
|
+
const root = get2(this._nodeOrThrow(id));
|
|
194
|
+
return toJSON2(root);
|
|
195
|
+
}).pipe(Atom2.withLabel(`graph:json:${id}`));
|
|
116
196
|
});
|
|
117
197
|
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
118
198
|
this._registry = registry ?? Registry.make();
|
|
@@ -130,502 +210,705 @@ var Graph = class {
|
|
|
130
210
|
});
|
|
131
211
|
}
|
|
132
212
|
}
|
|
133
|
-
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
json(id = ROOT_ID) {
|
|
137
|
-
return this._json(id);
|
|
213
|
+
json(id = RootId) {
|
|
214
|
+
return jsonImpl(this, id);
|
|
138
215
|
}
|
|
139
216
|
node(id) {
|
|
140
|
-
return this
|
|
217
|
+
return nodeImpl(this, id);
|
|
141
218
|
}
|
|
142
219
|
nodeOrThrow(id) {
|
|
143
|
-
return this
|
|
220
|
+
return nodeOrThrowImpl(this, id);
|
|
144
221
|
}
|
|
145
222
|
connections(id, relation = "outbound") {
|
|
146
|
-
return this
|
|
223
|
+
return connectionsImpl(this, id, relation);
|
|
147
224
|
}
|
|
148
225
|
actions(id) {
|
|
149
|
-
return this
|
|
226
|
+
return actionsImpl(this, id);
|
|
150
227
|
}
|
|
151
228
|
edges(id) {
|
|
152
|
-
return this
|
|
229
|
+
return edgesImpl(this, id);
|
|
153
230
|
}
|
|
154
|
-
|
|
155
|
-
|
|
231
|
+
/** @internal */
|
|
232
|
+
_constructNode(node) {
|
|
233
|
+
return Option.some({
|
|
234
|
+
[graphSymbol]: this,
|
|
235
|
+
data: null,
|
|
236
|
+
properties: {},
|
|
237
|
+
...node
|
|
238
|
+
});
|
|
156
239
|
}
|
|
157
|
-
|
|
158
|
-
|
|
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);
|
|
159
283
|
}
|
|
160
|
-
|
|
161
|
-
|
|
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);
|
|
162
296
|
}
|
|
163
|
-
|
|
164
|
-
|
|
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);
|
|
165
315
|
}
|
|
166
|
-
|
|
167
|
-
|
|
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);
|
|
168
328
|
}
|
|
169
|
-
|
|
170
|
-
|
|
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);
|
|
171
341
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}, {
|
|
178
|
-
F: __dxlog_file,
|
|
179
|
-
L: 399,
|
|
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
|
-
}
|
|
342
|
+
}
|
|
343
|
+
var traverseImpl = (graph, options, path = []) => {
|
|
344
|
+
const { visitor, source = RootId, relation = "outbound" } = options;
|
|
345
|
+
if (path.includes(source)) {
|
|
346
|
+
return;
|
|
187
347
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
348
|
+
const node = getNodeOrThrow(graph, source);
|
|
349
|
+
const shouldContinue = visitor(node, [
|
|
350
|
+
...path,
|
|
351
|
+
source
|
|
352
|
+
]);
|
|
353
|
+
if (shouldContinue === false) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
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);
|
|
375
|
+
}
|
|
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
|
+
}
|
|
199
390
|
});
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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);
|
|
203
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);
|
|
204
429
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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);
|
|
209
446
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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", {
|
|
260
553
|
id,
|
|
261
554
|
type,
|
|
262
555
|
data,
|
|
263
556
|
properties
|
|
264
557
|
}, {
|
|
265
558
|
F: __dxlog_file,
|
|
266
|
-
L:
|
|
267
|
-
S:
|
|
559
|
+
L: 854,
|
|
560
|
+
S: void 0,
|
|
268
561
|
C: (f, a) => f(...a)
|
|
269
562
|
});
|
|
270
|
-
const newNode =
|
|
271
|
-
|
|
563
|
+
const newNode = Option.some({
|
|
564
|
+
...existing,
|
|
565
|
+
...rest,
|
|
272
566
|
type,
|
|
273
567
|
data,
|
|
274
|
-
properties
|
|
568
|
+
properties: {
|
|
569
|
+
...existing.properties,
|
|
570
|
+
...properties
|
|
571
|
+
}
|
|
275
572
|
});
|
|
276
|
-
|
|
277
|
-
|
|
573
|
+
internal._registry.set(nodeAtom, newNode);
|
|
574
|
+
graph.onNodeChanged.emit({
|
|
278
575
|
id,
|
|
279
576
|
node: newNode
|
|
280
577
|
});
|
|
281
578
|
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
this.addEdges(_edges);
|
|
290
|
-
}
|
|
291
|
-
if (edges) {
|
|
292
|
-
todo();
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
removeNodes(ids, edges = false) {
|
|
296
|
-
Atom.batch(() => {
|
|
297
|
-
ids.map((id) => this.removeNode(id, edges));
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
removeNode(id, edges = false) {
|
|
301
|
-
const nodeAtom = this._node(id);
|
|
302
|
-
this._registry.set(nodeAtom, Option.none());
|
|
303
|
-
this.onNodeChanged.emit({
|
|
304
|
-
id,
|
|
305
|
-
node: Option.none()
|
|
306
|
-
});
|
|
307
|
-
if (edges) {
|
|
308
|
-
const { inbound, outbound } = this._registry.get(this._edges(id));
|
|
309
|
-
const edges2 = [
|
|
310
|
-
...inbound.map((source) => ({
|
|
311
|
-
source,
|
|
312
|
-
target: id
|
|
313
|
-
})),
|
|
314
|
-
...outbound.map((target) => ({
|
|
315
|
-
source: id,
|
|
316
|
-
target
|
|
317
|
-
}))
|
|
318
|
-
];
|
|
319
|
-
this.removeEdges(edges2);
|
|
320
|
-
}
|
|
321
|
-
this._onRemoveNode?.(id);
|
|
322
|
-
}
|
|
323
|
-
addEdges(edges) {
|
|
324
|
-
Atom.batch(() => {
|
|
325
|
-
edges.map((edge) => this.addEdge(edge));
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
addEdge(edgeArg) {
|
|
329
|
-
const sourceAtom = this._edges(edgeArg.source);
|
|
330
|
-
const source = this._registry.get(sourceAtom);
|
|
331
|
-
if (!source.outbound.includes(edgeArg.target)) {
|
|
332
|
-
log("add outbound edge", {
|
|
333
|
-
source: edgeArg.source,
|
|
334
|
-
target: edgeArg.target
|
|
579
|
+
},
|
|
580
|
+
onNone: () => {
|
|
581
|
+
log("new node", {
|
|
582
|
+
id,
|
|
583
|
+
type,
|
|
584
|
+
data,
|
|
585
|
+
properties
|
|
335
586
|
}, {
|
|
336
587
|
F: __dxlog_file,
|
|
337
|
-
L:
|
|
338
|
-
S:
|
|
588
|
+
L: 867,
|
|
589
|
+
S: void 0,
|
|
339
590
|
C: (f, a) => f(...a)
|
|
340
591
|
});
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
const targetAtom = this._edges(edgeArg.target);
|
|
350
|
-
const target = this._registry.get(targetAtom);
|
|
351
|
-
if (!target.inbound.includes(edgeArg.source)) {
|
|
352
|
-
log("add inbound edge", {
|
|
353
|
-
source: edgeArg.source,
|
|
354
|
-
target: edgeArg.target
|
|
355
|
-
}, {
|
|
356
|
-
F: __dxlog_file,
|
|
357
|
-
L: 518,
|
|
358
|
-
S: this,
|
|
359
|
-
C: (f, a) => f(...a)
|
|
592
|
+
const newNode = internal._constructNode({
|
|
593
|
+
id,
|
|
594
|
+
type,
|
|
595
|
+
data,
|
|
596
|
+
properties,
|
|
597
|
+
...rest
|
|
360
598
|
});
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
],
|
|
366
|
-
outbound: target.outbound
|
|
599
|
+
internal._registry.set(nodeAtom, newNode);
|
|
600
|
+
graph.onNodeChanged.emit({
|
|
601
|
+
id,
|
|
602
|
+
node: newNode
|
|
367
603
|
});
|
|
368
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);
|
|
613
|
+
}
|
|
614
|
+
if (edges) {
|
|
615
|
+
todo();
|
|
616
|
+
}
|
|
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);
|
|
626
|
+
}
|
|
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);
|
|
644
|
+
}
|
|
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);
|
|
667
|
+
}
|
|
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);
|
|
369
681
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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);
|
|
696
|
+
}
|
|
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
|
|
717
|
+
]
|
|
373
718
|
});
|
|
374
719
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
const target2 = this._registry.get(targetAtom);
|
|
395
|
-
if (source2.outbound.length === 0 && source2.inbound.length === 0 && edgeArg.source !== ROOT_ID) {
|
|
396
|
-
this.removeNodes([
|
|
397
|
-
edgeArg.source
|
|
398
|
-
]);
|
|
399
|
-
}
|
|
400
|
-
if (target2.outbound.length === 0 && target2.inbound.length === 0 && edgeArg.target !== ROOT_ID) {
|
|
401
|
-
this.removeNodes([
|
|
402
|
-
edgeArg.target
|
|
403
|
-
]);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
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
|
+
});
|
|
406
739
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
this._registry.set(edgesAtom, edges);
|
|
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);
|
|
417
749
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
...path,
|
|
436
|
-
source
|
|
437
|
-
]));
|
|
438
|
-
}
|
|
439
|
-
getPath({ source = "root", target }) {
|
|
440
|
-
return Function.pipe(this.getNode(source), Option.flatMap((node) => {
|
|
441
|
-
let found = Option.none();
|
|
442
|
-
this.traverse({
|
|
443
|
-
source: node.id,
|
|
444
|
-
visitor: (node2, path) => {
|
|
445
|
-
if (Option.isSome(found)) {
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
if (node2.id === target) {
|
|
449
|
-
found = Option.some(path);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
return found;
|
|
454
|
-
}));
|
|
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);
|
|
455
767
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
}, interval);
|
|
468
|
-
return trigger.wait({
|
|
469
|
-
timeout
|
|
470
|
-
}).finally(() => clearInterval(i));
|
|
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
|
+
});
|
|
471
778
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
...node
|
|
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
|
|
479
785
|
});
|
|
480
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
|
+
]);
|
|
794
|
+
}
|
|
795
|
+
if (target2.outbound.length === 0 && target2.inbound.length === 0 && edgeArg.target !== RootId) {
|
|
796
|
+
removeNodesImpl(graph, [
|
|
797
|
+
edgeArg.target
|
|
798
|
+
]);
|
|
799
|
+
}
|
|
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);
|
|
481
817
|
};
|
|
482
818
|
|
|
483
819
|
// src/graph-builder.ts
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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";
|
|
487
838
|
import * as Function2 from "effect/Function";
|
|
488
|
-
import * as
|
|
839
|
+
import * as Option3 from "effect/Option";
|
|
840
|
+
import * as Pipeable2 from "effect/Pipeable";
|
|
489
841
|
import * as Record2 from "effect/Record";
|
|
490
842
|
import { log as log2 } from "@dxos/log";
|
|
491
843
|
import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
492
844
|
|
|
493
|
-
// src/node.ts
|
|
494
|
-
var
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
+
}
|
|
872
|
+
}
|
|
873
|
+
return Option2.some(node);
|
|
874
|
+
};
|
|
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
|
+
}
|
|
881
|
+
}
|
|
882
|
+
return Option2.none();
|
|
883
|
+
};
|
|
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();
|
|
499
887
|
|
|
500
888
|
// src/graph-builder.ts
|
|
501
889
|
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
502
|
-
var
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const actionGroups = _actionGroups && Atom2.family((node) => _actionGroups(node).pipe(Atom2.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
508
|
-
const actions = _actions && Atom2.family((node) => _actions(node).pipe(Atom2.withLabel(`graph-builder:_actions:${id}`)));
|
|
509
|
-
return [
|
|
510
|
-
resolver ? {
|
|
511
|
-
id: getId("resolver"),
|
|
512
|
-
position,
|
|
513
|
-
resolver
|
|
514
|
-
} : void 0,
|
|
515
|
-
connector ? {
|
|
516
|
-
id: getId("connector"),
|
|
517
|
-
position,
|
|
518
|
-
relation,
|
|
519
|
-
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
520
|
-
try {
|
|
521
|
-
return get2(connector(node));
|
|
522
|
-
} catch {
|
|
523
|
-
log2.warn("Error in connector", {
|
|
524
|
-
id: getId("connector"),
|
|
525
|
-
node
|
|
526
|
-
}, {
|
|
527
|
-
F: __dxlog_file2,
|
|
528
|
-
L: 114,
|
|
529
|
-
S: void 0,
|
|
530
|
-
C: (f, a) => f(...a)
|
|
531
|
-
});
|
|
532
|
-
return [];
|
|
533
|
-
}
|
|
534
|
-
}).pipe(Atom2.withLabel(`graph-builder:connector:${id}`)))
|
|
535
|
-
} : void 0,
|
|
536
|
-
actionGroups ? {
|
|
537
|
-
id: getId("actionGroups"),
|
|
538
|
-
position,
|
|
539
|
-
relation: "outbound",
|
|
540
|
-
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
541
|
-
try {
|
|
542
|
-
return get2(actionGroups(node)).map((arg) => ({
|
|
543
|
-
...arg,
|
|
544
|
-
data: actionGroupSymbol,
|
|
545
|
-
type: ACTION_GROUP_TYPE
|
|
546
|
-
}));
|
|
547
|
-
} catch {
|
|
548
|
-
log2.warn("Error in actionGroups", {
|
|
549
|
-
id: getId("actionGroups"),
|
|
550
|
-
node
|
|
551
|
-
}, {
|
|
552
|
-
F: __dxlog_file2,
|
|
553
|
-
L: 135,
|
|
554
|
-
S: void 0,
|
|
555
|
-
C: (f, a) => f(...a)
|
|
556
|
-
});
|
|
557
|
-
return [];
|
|
558
|
-
}
|
|
559
|
-
}).pipe(Atom2.withLabel(`graph-builder:connector:actionGroups:${id}`)))
|
|
560
|
-
} : void 0,
|
|
561
|
-
actions ? {
|
|
562
|
-
id: getId("actions"),
|
|
563
|
-
position,
|
|
564
|
-
relation: "outbound",
|
|
565
|
-
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
566
|
-
try {
|
|
567
|
-
return get2(actions(node)).map((arg) => ({
|
|
568
|
-
...arg,
|
|
569
|
-
type: ACTION_TYPE
|
|
570
|
-
}));
|
|
571
|
-
} catch {
|
|
572
|
-
log2.warn("Error in actions", {
|
|
573
|
-
id: getId("actions"),
|
|
574
|
-
node
|
|
575
|
-
}, {
|
|
576
|
-
F: __dxlog_file2,
|
|
577
|
-
L: 152,
|
|
578
|
-
S: void 0,
|
|
579
|
-
C: (f, a) => f(...a)
|
|
580
|
-
});
|
|
581
|
-
return [];
|
|
582
|
-
}
|
|
583
|
-
}).pipe(Atom2.withLabel(`graph-builder:connector:actions:${id}`)))
|
|
584
|
-
} : void 0
|
|
585
|
-
].filter(isNonNullable2);
|
|
586
|
-
};
|
|
587
|
-
var flattenExtensions = (extension, acc = []) => {
|
|
588
|
-
if (Array.isArray(extension)) {
|
|
589
|
-
return [
|
|
590
|
-
...acc,
|
|
591
|
-
...extension.flatMap((ext) => flattenExtensions(ext, acc))
|
|
592
|
-
];
|
|
593
|
-
} else {
|
|
594
|
-
return [
|
|
595
|
-
...acc,
|
|
596
|
-
extension
|
|
597
|
-
];
|
|
890
|
+
var GraphBuilderTypeId = Symbol.for("@dxos/app-graph/GraphBuilder");
|
|
891
|
+
var GraphBuilderImpl = class {
|
|
892
|
+
[GraphBuilderTypeId] = GraphBuilderTypeId;
|
|
893
|
+
pipe() {
|
|
894
|
+
return Pipeable2.pipeArguments(this, arguments);
|
|
598
895
|
}
|
|
599
|
-
};
|
|
600
|
-
var GraphBuilder = class _GraphBuilder {
|
|
601
896
|
// TODO(wittjosiah): Use Context.
|
|
602
897
|
_subscriptions = /* @__PURE__ */ new Map();
|
|
603
|
-
_extensions =
|
|
898
|
+
_extensions = Atom3.make(Record2.empty()).pipe(Atom3.keepAlive, Atom3.withLabel("graph-builder:extensions"));
|
|
604
899
|
_initialized = {};
|
|
605
900
|
_registry;
|
|
606
901
|
_graph;
|
|
607
902
|
constructor({ registry, ...params } = {}) {
|
|
608
903
|
this._registry = registry ?? Registry2.make();
|
|
609
|
-
|
|
904
|
+
const graph = make({
|
|
610
905
|
...params,
|
|
611
906
|
registry: this._registry,
|
|
612
907
|
onExpand: (id, relation) => this._onExpand(id, relation),
|
|
613
908
|
onInitialize: (id) => this._onInitialize(id),
|
|
614
909
|
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
615
910
|
});
|
|
616
|
-
|
|
617
|
-
static from(pickle, registry) {
|
|
618
|
-
if (!pickle) {
|
|
619
|
-
return new _GraphBuilder({
|
|
620
|
-
registry
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
const { nodes, edges } = JSON.parse(pickle);
|
|
624
|
-
return new _GraphBuilder({
|
|
625
|
-
nodes,
|
|
626
|
-
edges,
|
|
627
|
-
registry
|
|
628
|
-
});
|
|
911
|
+
this._graph = graph;
|
|
629
912
|
}
|
|
630
913
|
get graph() {
|
|
631
914
|
return this._graph;
|
|
@@ -633,76 +916,26 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
633
916
|
get extensions() {
|
|
634
917
|
return this._extensions;
|
|
635
918
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
this._registry.set(this._extensions, Record2.set(extensions2, extension.id, extension));
|
|
640
|
-
});
|
|
641
|
-
return this;
|
|
642
|
-
}
|
|
643
|
-
removeExtension(id) {
|
|
644
|
-
const extensions = this._registry.get(this._extensions);
|
|
645
|
-
this._registry.set(this._extensions, Record2.remove(extensions, id));
|
|
646
|
-
return this;
|
|
647
|
-
}
|
|
648
|
-
async explore({ registry = Registry2.make(), source = ROOT_ID, relation = "outbound", visitor }, path = []) {
|
|
649
|
-
if (path.includes(source)) {
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
if (!isNode()) {
|
|
653
|
-
const { yieldOrContinue } = await import("main-thread-scheduling");
|
|
654
|
-
await yieldOrContinue("idle");
|
|
655
|
-
}
|
|
656
|
-
const node = registry.get(this._graph.nodeOrThrow(source));
|
|
657
|
-
const shouldContinue = await visitor(node, [
|
|
658
|
-
...path,
|
|
659
|
-
node.id
|
|
660
|
-
]);
|
|
661
|
-
if (shouldContinue === false) {
|
|
662
|
-
return;
|
|
663
|
-
}
|
|
664
|
-
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))));
|
|
665
|
-
await Promise.all(nodes.map((nodeArg) => {
|
|
666
|
-
registry.set(this._graph._node(nodeArg.id), this._graph._constructNode(nodeArg));
|
|
667
|
-
return this.explore({
|
|
668
|
-
registry,
|
|
669
|
-
source: nodeArg.id,
|
|
670
|
-
relation,
|
|
671
|
-
visitor
|
|
672
|
-
}, [
|
|
673
|
-
...path,
|
|
674
|
-
node.id
|
|
675
|
-
]);
|
|
676
|
-
}));
|
|
677
|
-
if (registry !== this._registry) {
|
|
678
|
-
registry.reset();
|
|
679
|
-
registry.dispose();
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
destroy() {
|
|
683
|
-
this._subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
684
|
-
this._subscriptions.clear();
|
|
685
|
-
}
|
|
686
|
-
_resolvers = Atom2.family((id) => {
|
|
687
|
-
return Atom2.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);
|
|
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);
|
|
689
922
|
});
|
|
690
923
|
});
|
|
691
|
-
_connectors =
|
|
692
|
-
return
|
|
924
|
+
_connectors = Atom3.family((key) => {
|
|
925
|
+
return Atom3.make((get2) => {
|
|
693
926
|
const [id, relation] = key.split("+");
|
|
694
927
|
const node = this._graph.node(id);
|
|
695
928
|
return Function2.pipe(
|
|
696
929
|
get2(this._extensions),
|
|
697
930
|
Record2.values,
|
|
698
931
|
// TODO(wittjosiah): Sort on write rather than read.
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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))
|
|
704
937
|
);
|
|
705
|
-
}).pipe(
|
|
938
|
+
}).pipe(Atom3.withLabel(`graph-builder:connectors:${key}`));
|
|
706
939
|
});
|
|
707
940
|
_onExpand(id, relation) {
|
|
708
941
|
log2("onExpand", {
|
|
@@ -711,7 +944,7 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
711
944
|
registry: getDebugName(this._registry)
|
|
712
945
|
}, {
|
|
713
946
|
F: __dxlog_file2,
|
|
714
|
-
L:
|
|
947
|
+
L: 176,
|
|
715
948
|
S: this,
|
|
716
949
|
C: (f, a) => f(...a)
|
|
717
950
|
});
|
|
@@ -728,25 +961,25 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
728
961
|
removed
|
|
729
962
|
}, {
|
|
730
963
|
F: __dxlog_file2,
|
|
731
|
-
L:
|
|
964
|
+
L: 187,
|
|
732
965
|
S: this,
|
|
733
966
|
C: (f, a) => f(...a)
|
|
734
967
|
});
|
|
735
968
|
const update = () => {
|
|
736
|
-
|
|
737
|
-
this._graph
|
|
969
|
+
Atom3.batch(() => {
|
|
970
|
+
removeEdges(this._graph, removed.map((target) => ({
|
|
738
971
|
source: id,
|
|
739
972
|
target
|
|
740
973
|
})), true);
|
|
741
|
-
this._graph
|
|
742
|
-
this._graph
|
|
974
|
+
addNodes(this._graph, nodes);
|
|
975
|
+
addEdges(this._graph, nodes.map((node) => relation === "outbound" ? {
|
|
743
976
|
source: id,
|
|
744
977
|
target: node.id
|
|
745
978
|
} : {
|
|
746
979
|
source: node.id,
|
|
747
980
|
target: id
|
|
748
981
|
}));
|
|
749
|
-
this._graph
|
|
982
|
+
sortEdges(this._graph, id, relation, nodes.map(({ id: id2 }) => id2));
|
|
750
983
|
});
|
|
751
984
|
};
|
|
752
985
|
if (typeof requestAnimationFrame === "function") {
|
|
@@ -765,23 +998,23 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
765
998
|
id
|
|
766
999
|
}, {
|
|
767
1000
|
F: __dxlog_file2,
|
|
768
|
-
L:
|
|
1001
|
+
L: 227,
|
|
769
1002
|
S: this,
|
|
770
1003
|
C: (f, a) => f(...a)
|
|
771
1004
|
});
|
|
772
1005
|
const resolver = this._resolvers(id);
|
|
773
1006
|
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
774
1007
|
const trigger = this._initialized[id];
|
|
775
|
-
|
|
1008
|
+
Option3.match(node, {
|
|
776
1009
|
onSome: (node2) => {
|
|
777
|
-
this._graph
|
|
1010
|
+
addNodes(this._graph, [
|
|
778
1011
|
node2
|
|
779
1012
|
]);
|
|
780
1013
|
trigger?.wake();
|
|
781
1014
|
},
|
|
782
1015
|
onNone: () => {
|
|
783
1016
|
trigger?.wake();
|
|
784
|
-
this._graph
|
|
1017
|
+
removeNodes(this._graph, [
|
|
785
1018
|
id
|
|
786
1019
|
]);
|
|
787
1020
|
}
|
|
@@ -796,41 +1029,269 @@ var GraphBuilder = class _GraphBuilder {
|
|
|
796
1029
|
this._subscriptions.delete(id);
|
|
797
1030
|
}
|
|
798
1031
|
};
|
|
799
|
-
var
|
|
800
|
-
return
|
|
801
|
-
|
|
802
|
-
|
|
1032
|
+
var make2 = (params) => {
|
|
1033
|
+
return new GraphBuilderImpl(params);
|
|
1034
|
+
};
|
|
1035
|
+
var from = (pickle, registry) => {
|
|
1036
|
+
if (!pickle) {
|
|
1037
|
+
return make2({
|
|
1038
|
+
registry
|
|
803
1039
|
});
|
|
804
|
-
|
|
805
|
-
|
|
1040
|
+
}
|
|
1041
|
+
const { nodes, edges } = JSON.parse(pickle);
|
|
1042
|
+
return make2({
|
|
1043
|
+
nodes,
|
|
1044
|
+
edges,
|
|
1045
|
+
registry
|
|
806
1046
|
});
|
|
807
1047
|
};
|
|
808
|
-
var
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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));
|
|
1053
|
+
});
|
|
1054
|
+
return builder;
|
|
1055
|
+
};
|
|
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
|
|
813
1258
|
});
|
|
814
1259
|
});
|
|
815
|
-
var
|
|
816
|
-
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
|
+
}
|
|
817
1289
|
};
|
|
818
1290
|
export {
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
ROOT_TYPE,
|
|
825
|
-
actionGroupSymbol,
|
|
826
|
-
atomFromObservable,
|
|
827
|
-
atomFromSignal,
|
|
828
|
-
createExtension,
|
|
829
|
-
flattenExtensions,
|
|
830
|
-
getGraph,
|
|
831
|
-
isAction,
|
|
832
|
-
isActionGroup,
|
|
833
|
-
isActionLike,
|
|
834
|
-
isGraphNode
|
|
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
|
|
835
1296
|
};
|
|
836
1297
|
//# sourceMappingURL=index.mjs.map
|