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