@dxos/app-graph 0.8.4-main.c85a9c8dae → 0.8.4-main.d05539e30a
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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/{browser/index.mjs → neutral/chunk-32XXJE6M.mjs} +304 -349
- package/dist/lib/neutral/chunk-32XXJE6M.mjs.map +7 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +40 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/scheduler.mjs +15 -0
- package/dist/lib/neutral/scheduler.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +40 -0
- package/dist/lib/neutral/testing/index.mjs.map +7 -0
- package/dist/types/src/atoms.d.ts.map +1 -1
- package/dist/types/src/graph-builder.d.ts +3 -3
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +2 -2
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/node-matcher.d.ts +44 -18
- package/dist/types/src/node-matcher.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +11 -3
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/scheduler.browser.d.ts +2 -0
- package/dist/types/src/scheduler.browser.d.ts.map +1 -0
- package/dist/types/src/scheduler.d.ts +8 -0
- package/dist/types/src/scheduler.d.ts.map +1 -0
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/setup-graph-builder.d.ts +31 -0
- package/dist/types/src/testing/setup-graph-builder.d.ts.map +1 -0
- package/dist/types/src/util.d.ts +26 -10
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +38 -27
- package/src/graph-builder.test.ts +536 -34
- package/src/graph-builder.ts +87 -24
- package/src/graph.test.ts +21 -1
- package/src/graph.ts +32 -21
- package/src/index.ts +1 -0
- package/src/node-matcher.ts +59 -27
- package/src/node.ts +32 -3
- package/src/scheduler.browser.ts +5 -0
- package/src/scheduler.ts +17 -0
- package/src/stories/EchoGraph.stories.tsx +13 -15
- package/src/testing/index.ts +5 -0
- package/src/testing/setup-graph-builder.ts +41 -0
- package/src/util.ts +59 -13
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/node-esm/index.mjs +0 -1523
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
|
@@ -1,67 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
24
|
-
// src/graph.ts
|
|
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
|
-
relationFromKey: () => relationFromKey,
|
|
45
|
-
relationKey: () => relationKey,
|
|
46
|
-
removeEdge: () => removeEdge,
|
|
47
|
-
removeEdges: () => removeEdges,
|
|
48
|
-
removeNode: () => removeNode,
|
|
49
|
-
removeNodes: () => removeNodes,
|
|
50
|
-
sortEdges: () => sortEdges,
|
|
51
|
-
toJSON: () => toJSON,
|
|
52
|
-
traverse: () => traverse,
|
|
53
|
-
waitForPath: () => waitForPath
|
|
54
|
-
});
|
|
55
|
-
import { Atom as Atom2, Registry } from "@effect-atom/atom-react";
|
|
56
|
-
import * as Function from "effect/Function";
|
|
57
|
-
import * as Option from "effect/Option";
|
|
58
|
-
import * as Pipeable from "effect/Pipeable";
|
|
59
|
-
import * as Record from "effect/Record";
|
|
60
|
-
import { Event, Trigger } from "@dxos/async";
|
|
61
|
-
import { todo } from "@dxos/debug";
|
|
62
|
-
import { invariant } from "@dxos/invariant";
|
|
63
|
-
import { log } from "@dxos/log";
|
|
64
|
-
import { isNonNullable } from "@dxos/util";
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-J5LGTIGS.mjs";
|
|
65
4
|
|
|
66
5
|
// src/node.ts
|
|
67
6
|
var node_exports = {};
|
|
@@ -77,12 +16,15 @@ __export(node_exports, {
|
|
|
77
16
|
isActionGroup: () => isActionGroup,
|
|
78
17
|
isActionLike: () => isActionLike,
|
|
79
18
|
isGraphNode: () => isGraphNode,
|
|
19
|
+
make: () => make,
|
|
20
|
+
makeAction: () => makeAction,
|
|
21
|
+
makeActionGroup: () => makeActionGroup,
|
|
80
22
|
relation: () => relation
|
|
81
23
|
});
|
|
82
24
|
var RootId = "root";
|
|
83
|
-
var RootType = "dxos.
|
|
84
|
-
var ActionType = "dxos.
|
|
85
|
-
var ActionGroupType = "dxos.
|
|
25
|
+
var RootType = "org.dxos.type.graphRoot";
|
|
26
|
+
var ActionType = "org.dxos.type.graphAction";
|
|
27
|
+
var ActionGroupType = "org.dxos.type.graphActionGroup";
|
|
86
28
|
var relation = (kind, direction = "outbound") => ({
|
|
87
29
|
kind,
|
|
88
30
|
direction
|
|
@@ -94,16 +36,35 @@ var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" &&
|
|
|
94
36
|
var actionGroupSymbol = /* @__PURE__ */ Symbol("ActionGroup");
|
|
95
37
|
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ActionGroupType : false;
|
|
96
38
|
var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
39
|
+
var make = (arg) => arg;
|
|
40
|
+
var makeAction = (arg) => ({
|
|
41
|
+
...arg,
|
|
42
|
+
type: ActionType
|
|
43
|
+
});
|
|
44
|
+
var makeActionGroup = (arg) => ({
|
|
45
|
+
...arg,
|
|
46
|
+
type: ActionGroupType,
|
|
47
|
+
data: actionGroupSymbol
|
|
48
|
+
});
|
|
97
49
|
|
|
98
50
|
// src/util.ts
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
51
|
+
import { invariant } from "@dxos/invariant";
|
|
52
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-graph/src/util.ts";
|
|
53
|
+
var PRIMARY = "";
|
|
54
|
+
var SECONDARY = "";
|
|
55
|
+
var PATH = "/";
|
|
56
|
+
var primaryKey = (...parts) => parts.join(PRIMARY);
|
|
57
|
+
var primaryParts = (key) => key.split(PRIMARY);
|
|
58
|
+
var secondaryKey = (...parts) => parts.join(SECONDARY);
|
|
59
|
+
var secondaryParts = (key) => key.split(SECONDARY);
|
|
103
60
|
var normalizeRelation = (relation2) => relation2 == null ? childRelation() : typeof relation2 === "string" ? relation(relation2) : relation2;
|
|
104
61
|
var shallowEqual = (a, b) => {
|
|
105
|
-
if (a === b)
|
|
106
|
-
|
|
62
|
+
if (a === b) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (a == null || b == null || typeof a !== "object" || typeof b !== "object") {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
107
68
|
const keysA = Object.keys(a);
|
|
108
69
|
const keysB = Object.keys(b);
|
|
109
70
|
if (keysA.length !== keysB.length) {
|
|
@@ -117,24 +78,70 @@ var nodeArgsUnchanged = (prev, next) => {
|
|
|
117
78
|
}
|
|
118
79
|
return prev.every((prevNode, idx) => {
|
|
119
80
|
const nextNode = next[idx];
|
|
120
|
-
return prevNode.id === nextNode.id && prevNode.type === nextNode.type && shallowEqual(prevNode.data, nextNode.data) && shallowEqual(prevNode.properties, nextNode.properties);
|
|
81
|
+
return prevNode.id === nextNode.id && prevNode.type === nextNode.type && shallowEqual(prevNode.data, nextNode.data) && shallowEqual(prevNode.properties, nextNode.properties) && nodeArgsUnchanged(prevNode.nodes ?? [], nextNode.nodes ?? []);
|
|
121
82
|
});
|
|
122
83
|
};
|
|
84
|
+
var qualifyId = (parentId, ...segmentIds) => [
|
|
85
|
+
parentId,
|
|
86
|
+
...segmentIds
|
|
87
|
+
].join(PATH);
|
|
88
|
+
var validateSegmentId = (id) => {
|
|
89
|
+
invariant(!id.includes(PATH), `Node segment ID must not contain '${PATH}': ${id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 56, S: void 0, A: ["!id.includes(PATH)", "`Node segment ID must not contain '${PATH}': ${id}`"] });
|
|
90
|
+
};
|
|
91
|
+
var getParentId = (qualifiedId) => {
|
|
92
|
+
const lastSlash = qualifiedId.lastIndexOf(PATH);
|
|
93
|
+
return lastSlash > 0 ? qualifiedId.slice(0, lastSlash) : void 0;
|
|
94
|
+
};
|
|
95
|
+
var getSegmentId = (qualifiedId) => {
|
|
96
|
+
return qualifiedId.split(PATH).pop() ?? qualifiedId;
|
|
97
|
+
};
|
|
123
98
|
|
|
124
99
|
// src/graph.ts
|
|
125
|
-
var
|
|
100
|
+
var graph_exports = {};
|
|
101
|
+
__export(graph_exports, {
|
|
102
|
+
GraphKind: () => GraphKind,
|
|
103
|
+
GraphTypeId: () => GraphTypeId,
|
|
104
|
+
addEdge: () => addEdge,
|
|
105
|
+
addEdges: () => addEdges,
|
|
106
|
+
addNode: () => addNode,
|
|
107
|
+
addNodes: () => addNodes,
|
|
108
|
+
expand: () => expand,
|
|
109
|
+
getActions: () => getActions,
|
|
110
|
+
getConnections: () => getConnections,
|
|
111
|
+
getEdges: () => getEdges,
|
|
112
|
+
getGraph: () => getGraph,
|
|
113
|
+
getNode: () => getNode,
|
|
114
|
+
getNodeOrThrow: () => getNodeOrThrow,
|
|
115
|
+
getPath: () => getPath,
|
|
116
|
+
getRoot: () => getRoot,
|
|
117
|
+
initialize: () => initialize,
|
|
118
|
+
make: () => make2,
|
|
119
|
+
relationFromKey: () => relationFromKey,
|
|
120
|
+
relationKey: () => relationKey,
|
|
121
|
+
removeEdge: () => removeEdge,
|
|
122
|
+
removeEdges: () => removeEdges,
|
|
123
|
+
removeNode: () => removeNode,
|
|
124
|
+
removeNodes: () => removeNodes,
|
|
125
|
+
sortEdges: () => sortEdges,
|
|
126
|
+
toJSON: () => toJSON,
|
|
127
|
+
traverse: () => traverse,
|
|
128
|
+
waitForPath: () => waitForPath
|
|
129
|
+
});
|
|
130
|
+
import { Atom, Registry } from "@effect-atom/atom-react";
|
|
131
|
+
import * as Function from "effect/Function";
|
|
132
|
+
import * as Option from "effect/Option";
|
|
133
|
+
import * as Pipeable from "effect/Pipeable";
|
|
134
|
+
import * as Record from "effect/Record";
|
|
135
|
+
import { Event, Trigger } from "@dxos/async";
|
|
136
|
+
import { todo } from "@dxos/debug";
|
|
137
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
138
|
+
import { log } from "@dxos/log";
|
|
139
|
+
import { isNonNullable } from "@dxos/util";
|
|
140
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
126
141
|
var graphSymbol = /* @__PURE__ */ Symbol("graph");
|
|
127
142
|
var getGraph = (node) => {
|
|
128
143
|
const graph = node[graphSymbol];
|
|
129
|
-
|
|
130
|
-
F: __dxlog_file,
|
|
131
|
-
L: 33,
|
|
132
|
-
S: void 0,
|
|
133
|
-
A: [
|
|
134
|
-
"graph",
|
|
135
|
-
"'Node is not associated with a graph.'"
|
|
136
|
-
]
|
|
137
|
-
});
|
|
144
|
+
invariant2(graph, "Node is not associated with a graph.", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 21, S: void 0, A: ["graph", "'Node is not associated with a graph.'"] });
|
|
138
145
|
return graph;
|
|
139
146
|
};
|
|
140
147
|
var GraphTypeId = /* @__PURE__ */ Symbol.for("@dxos/app-graph/Graph");
|
|
@@ -166,45 +173,44 @@ var GraphImpl = class {
|
|
|
166
173
|
]
|
|
167
174
|
]);
|
|
168
175
|
/** @internal */
|
|
169
|
-
_node =
|
|
176
|
+
_node = Atom.family((id) => {
|
|
170
177
|
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
171
|
-
return
|
|
178
|
+
return Atom.make(initial).pipe(Atom.keepAlive, Atom.withLabel(`graph:node:${id}`));
|
|
172
179
|
});
|
|
173
|
-
_nodeOrThrow =
|
|
174
|
-
return
|
|
180
|
+
_nodeOrThrow = Atom.family((id) => {
|
|
181
|
+
return Atom.make((get2) => {
|
|
175
182
|
const node = get2(this._node(id));
|
|
176
|
-
|
|
177
|
-
F: __dxlog_file,
|
|
178
|
-
L: 172,
|
|
179
|
-
S: this,
|
|
180
|
-
A: [
|
|
181
|
-
"Option.isSome(node)",
|
|
182
|
-
"`Node not available: ${id}`"
|
|
183
|
-
]
|
|
184
|
-
});
|
|
183
|
+
invariant2(Option.isSome(node), `Node not available: ${id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 67, S: this, A: ["Option.isSome(node)", "`Node not available: ${id}`"] });
|
|
185
184
|
return node.value;
|
|
186
185
|
});
|
|
187
186
|
});
|
|
188
|
-
_edges =
|
|
187
|
+
_edges = Atom.family((id) => {
|
|
189
188
|
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({})));
|
|
190
|
-
return
|
|
189
|
+
return Atom.make(initial).pipe(Atom.keepAlive, Atom.withLabel(`graph:edges:${id}`));
|
|
191
190
|
});
|
|
192
191
|
// NOTE: Currently the argument to the family needs to be referentially stable for the atom to be referentially stable.
|
|
193
192
|
// TODO(wittjosiah): Atom feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
194
|
-
_connections =
|
|
195
|
-
return
|
|
193
|
+
_connections = Atom.family((key) => {
|
|
194
|
+
return Atom.make((get2) => {
|
|
195
|
+
const parts = key ? primaryParts(key) : [];
|
|
196
|
+
if (parts.length < 2 || !parts[0]) {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
196
199
|
const { id, relation: relation2 } = relationFromConnectionKey(key);
|
|
197
200
|
const edges = get2(this._edges(id));
|
|
198
201
|
return (edges[relationKey(relation2)] ?? []).map((id2) => get2(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
199
|
-
}).pipe(
|
|
202
|
+
}).pipe(Atom.withLabel(`graph:connections:${key}`));
|
|
200
203
|
});
|
|
201
|
-
_actions =
|
|
202
|
-
return
|
|
204
|
+
_actions = Atom.family((id) => {
|
|
205
|
+
return Atom.make((get2) => {
|
|
206
|
+
if (!id) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
203
209
|
return get2(this._connections(connectionKey(id, actionRelation())));
|
|
204
|
-
}).pipe(
|
|
210
|
+
}).pipe(Atom.withLabel(`graph:actions:${id}`));
|
|
205
211
|
});
|
|
206
|
-
_json =
|
|
207
|
-
return
|
|
212
|
+
_json = Atom.family((id) => {
|
|
213
|
+
return Atom.make((get2) => {
|
|
208
214
|
const toJSON2 = (node, seen = []) => {
|
|
209
215
|
const nodes = get2(this._connections(connectionKey(node.id, "child")));
|
|
210
216
|
const obj = {
|
|
@@ -227,7 +233,7 @@ var GraphImpl = class {
|
|
|
227
233
|
};
|
|
228
234
|
const root = get2(this._nodeOrThrow(id));
|
|
229
235
|
return toJSON2(root);
|
|
230
|
-
}).pipe(
|
|
236
|
+
}).pipe(Atom.withLabel(`graph:json:${id}`));
|
|
231
237
|
});
|
|
232
238
|
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
233
239
|
this._registry = registry ?? Registry.make();
|
|
@@ -345,15 +351,7 @@ function getConnections(graphOrId, idOrRelation, relation2) {
|
|
|
345
351
|
} else {
|
|
346
352
|
const graph = graphOrId;
|
|
347
353
|
const id = idOrRelation;
|
|
348
|
-
|
|
349
|
-
F: __dxlog_file,
|
|
350
|
-
L: 440,
|
|
351
|
-
S: this,
|
|
352
|
-
A: [
|
|
353
|
-
"relation !== undefined",
|
|
354
|
-
"'Relation is required.'"
|
|
355
|
-
]
|
|
356
|
-
});
|
|
354
|
+
invariant2(relation2 !== void 0, "Relation is required.", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 272, S: this, A: ["relation !== undefined", "'Relation is required.'"] });
|
|
357
355
|
const rel = relation2;
|
|
358
356
|
return getConnectionsImpl(graph, id, rel);
|
|
359
357
|
}
|
|
@@ -397,14 +395,25 @@ var traverseImpl = (graph, options, path = []) => {
|
|
|
397
395
|
if (shouldContinue === false) {
|
|
398
396
|
return;
|
|
399
397
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
398
|
+
const relations = Array.isArray(relation2) ? relation2 : [
|
|
399
|
+
relation2
|
|
400
|
+
];
|
|
401
|
+
const seen = /* @__PURE__ */ new Set();
|
|
402
|
+
for (const rel of relations) {
|
|
403
|
+
for (const connected of getConnections(graph, source, rel)) {
|
|
404
|
+
if (!seen.has(connected.id)) {
|
|
405
|
+
seen.add(connected.id);
|
|
406
|
+
traverseImpl(graph, {
|
|
407
|
+
source: connected.id,
|
|
408
|
+
relation: relation2,
|
|
409
|
+
visitor
|
|
410
|
+
}, [
|
|
411
|
+
...path,
|
|
412
|
+
source
|
|
413
|
+
]);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
408
417
|
};
|
|
409
418
|
function traverse(graphOrOptions, optionsOrPath, path) {
|
|
410
419
|
if (typeof graphOrOptions === "object" && "visitor" in graphOrOptions) {
|
|
@@ -479,12 +488,7 @@ var initializeImpl = async (graph, id) => {
|
|
|
479
488
|
log("initialize", {
|
|
480
489
|
id,
|
|
481
490
|
initialized
|
|
482
|
-
}, {
|
|
483
|
-
F: __dxlog_file,
|
|
484
|
-
L: 655,
|
|
485
|
-
S: void 0,
|
|
486
|
-
C: (f, a) => f(...a)
|
|
487
|
-
});
|
|
491
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 431, S: void 0 });
|
|
488
492
|
if (!initialized) {
|
|
489
493
|
Record.set(internal._initialized, id, true);
|
|
490
494
|
await internal._onInitialize?.(id);
|
|
@@ -503,31 +507,21 @@ function initialize(graphOrId, id) {
|
|
|
503
507
|
var expandImpl = (graph, id, relation2) => {
|
|
504
508
|
const internal = getInternal(graph);
|
|
505
509
|
const normalizedRelation = normalizeRelation(relation2);
|
|
506
|
-
const key =
|
|
510
|
+
const key = primaryKey(id, relationKey(normalizedRelation));
|
|
507
511
|
const nodeOpt = internal._registry.get(internal._node(id));
|
|
508
512
|
if (Option.isNone(nodeOpt)) {
|
|
509
513
|
internal._pendingExpands.add(key);
|
|
510
514
|
log("expand", {
|
|
511
515
|
key,
|
|
512
516
|
deferred: true
|
|
513
|
-
}, {
|
|
514
|
-
F: __dxlog_file,
|
|
515
|
-
L: 701,
|
|
516
|
-
S: void 0,
|
|
517
|
-
C: (f, a) => f(...a)
|
|
518
|
-
});
|
|
517
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 463, S: void 0 });
|
|
519
518
|
return graph;
|
|
520
519
|
}
|
|
521
520
|
const expanded = Record.get(internal._expanded, key).pipe(Option.getOrElse(() => false));
|
|
522
521
|
log("expand", {
|
|
523
522
|
key,
|
|
524
523
|
expanded
|
|
525
|
-
}, {
|
|
526
|
-
F: __dxlog_file,
|
|
527
|
-
L: 706,
|
|
528
|
-
S: void 0,
|
|
529
|
-
C: (f, a) => f(...a)
|
|
530
|
-
});
|
|
524
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 470, S: void 0 });
|
|
531
525
|
if (!expanded) {
|
|
532
526
|
Record.set(internal._expanded, key, true);
|
|
533
527
|
internal._onExpand?.(id, normalizedRelation);
|
|
@@ -542,15 +536,7 @@ function expand(graphOrId, idOrRelation, relation2) {
|
|
|
542
536
|
} else {
|
|
543
537
|
const graph = graphOrId;
|
|
544
538
|
const id = idOrRelation;
|
|
545
|
-
|
|
546
|
-
F: __dxlog_file,
|
|
547
|
-
L: 742,
|
|
548
|
-
S: this,
|
|
549
|
-
A: [
|
|
550
|
-
"relation !== undefined",
|
|
551
|
-
"'Relation is required.'"
|
|
552
|
-
]
|
|
553
|
-
});
|
|
539
|
+
invariant2(relation2 !== void 0, "Relation is required.", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 490, S: this, A: ["relation !== undefined", "'Relation is required.'"] });
|
|
554
540
|
const rel = relation2;
|
|
555
541
|
return expandImpl(graph, id, rel);
|
|
556
542
|
}
|
|
@@ -590,7 +576,7 @@ function sortEdges(graphOrId, idOrRelation, relationOrOrder, order) {
|
|
|
590
576
|
}
|
|
591
577
|
}
|
|
592
578
|
var addNodesImpl = (graph, nodes) => {
|
|
593
|
-
|
|
579
|
+
Atom.batch(() => {
|
|
594
580
|
nodes.map((node) => addNodeImpl(graph, node));
|
|
595
581
|
});
|
|
596
582
|
return graph;
|
|
@@ -619,24 +605,14 @@ var addNodeImpl = (graph, nodeArg) => {
|
|
|
619
605
|
typeChanged,
|
|
620
606
|
dataChanged,
|
|
621
607
|
propertiesChanged
|
|
622
|
-
}, {
|
|
623
|
-
F: __dxlog_file,
|
|
624
|
-
L: 864,
|
|
625
|
-
S: void 0,
|
|
626
|
-
C: (f, a) => f(...a)
|
|
627
|
-
});
|
|
608
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 565, S: void 0 });
|
|
628
609
|
if (typeChanged || dataChanged || propertiesChanged) {
|
|
629
610
|
log("updating node", {
|
|
630
611
|
id,
|
|
631
612
|
type,
|
|
632
613
|
data,
|
|
633
614
|
properties
|
|
634
|
-
}, {
|
|
635
|
-
F: __dxlog_file,
|
|
636
|
-
L: 871,
|
|
637
|
-
S: void 0,
|
|
638
|
-
C: (f, a) => f(...a)
|
|
639
|
-
});
|
|
615
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 572, S: void 0 });
|
|
640
616
|
const newNode = Option.some({
|
|
641
617
|
...existing,
|
|
642
618
|
...rest,
|
|
@@ -660,12 +636,7 @@ var addNodeImpl = (graph, nodeArg) => {
|
|
|
660
636
|
type,
|
|
661
637
|
data,
|
|
662
638
|
properties
|
|
663
|
-
}, {
|
|
664
|
-
F: __dxlog_file,
|
|
665
|
-
L: 884,
|
|
666
|
-
S: void 0,
|
|
667
|
-
C: (f, a) => f(...a)
|
|
668
|
-
});
|
|
639
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 596, S: void 0 });
|
|
669
640
|
const newNode = internal._constructNode({
|
|
670
641
|
id,
|
|
671
642
|
type,
|
|
@@ -678,13 +649,12 @@ var addNodeImpl = (graph, nodeArg) => {
|
|
|
678
649
|
id,
|
|
679
650
|
node: newNode
|
|
680
651
|
});
|
|
681
|
-
const prefix = `${id}${Separators.primary}`;
|
|
682
652
|
const toApply = [
|
|
683
653
|
...internal._pendingExpands
|
|
684
|
-
].filter((k) => k
|
|
654
|
+
].filter((k) => primaryParts(k)[0] === id);
|
|
685
655
|
for (const pendingKey of toApply) {
|
|
686
656
|
internal._pendingExpands.delete(pendingKey);
|
|
687
|
-
const relation2 = relationFromKey(pendingKey
|
|
657
|
+
const relation2 = relationFromKey(primaryParts(pendingKey)[1]);
|
|
688
658
|
Record.set(internal._expanded, pendingKey, true);
|
|
689
659
|
internal._onExpand?.(id, relation2);
|
|
690
660
|
}
|
|
@@ -714,7 +684,7 @@ function addNode(graphOrNodeArg, nodeArg) {
|
|
|
714
684
|
}
|
|
715
685
|
}
|
|
716
686
|
var removeNodesImpl = (graph, ids, edges = false) => {
|
|
717
|
-
|
|
687
|
+
Atom.batch(() => {
|
|
718
688
|
ids.map((id) => removeNodeImpl(graph, id, edges));
|
|
719
689
|
});
|
|
720
690
|
return graph;
|
|
@@ -779,7 +749,7 @@ function removeNode(graphOrId, idOrEdges, edges) {
|
|
|
779
749
|
}
|
|
780
750
|
}
|
|
781
751
|
var addEdgesImpl = (graph, edges) => {
|
|
782
|
-
|
|
752
|
+
Atom.batch(() => {
|
|
783
753
|
edges.map((edge) => addEdgeImpl(graph, edge));
|
|
784
754
|
});
|
|
785
755
|
return graph;
|
|
@@ -807,12 +777,7 @@ var addEdgeImpl = (graph, edgeArg) => {
|
|
|
807
777
|
source: edgeArg.source,
|
|
808
778
|
target: edgeArg.target,
|
|
809
779
|
relation: relationId
|
|
810
|
-
}, {
|
|
811
|
-
F: __dxlog_file,
|
|
812
|
-
L: 1068,
|
|
813
|
-
S: void 0,
|
|
814
|
-
C: (f, a) => f(...a)
|
|
815
|
-
});
|
|
780
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 758, S: void 0 });
|
|
816
781
|
internal._registry.set(sourceAtom, {
|
|
817
782
|
...source,
|
|
818
783
|
[relationId]: [
|
|
@@ -829,12 +794,7 @@ var addEdgeImpl = (graph, edgeArg) => {
|
|
|
829
794
|
source: edgeArg.source,
|
|
830
795
|
target: edgeArg.target,
|
|
831
796
|
relation: inverseId
|
|
832
|
-
}, {
|
|
833
|
-
F: __dxlog_file,
|
|
834
|
-
L: 1076,
|
|
835
|
-
S: void 0,
|
|
836
|
-
C: (f, a) => f(...a)
|
|
837
|
-
});
|
|
797
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 775, S: void 0 });
|
|
838
798
|
internal._registry.set(targetAtom, {
|
|
839
799
|
...target,
|
|
840
800
|
[inverseId]: [
|
|
@@ -855,7 +815,7 @@ function addEdge(graphOrEdgeArg, edgeArg) {
|
|
|
855
815
|
}
|
|
856
816
|
}
|
|
857
817
|
var removeEdgesImpl = (graph, edges, removeOrphans = false) => {
|
|
858
|
-
|
|
818
|
+
Atom.batch(() => {
|
|
859
819
|
edges.map((edge) => removeEdgeImpl(graph, edge, removeOrphans));
|
|
860
820
|
});
|
|
861
821
|
return graph;
|
|
@@ -925,51 +885,24 @@ function removeEdge(graphOrEdgeArg, edgeArgOrRemoveOrphans, removeOrphans) {
|
|
|
925
885
|
return removeEdgeImpl(graph, edgeArg, removeOrphansArg);
|
|
926
886
|
}
|
|
927
887
|
}
|
|
928
|
-
var
|
|
888
|
+
var make2 = (params) => {
|
|
929
889
|
return new GraphImpl(params);
|
|
930
890
|
};
|
|
931
891
|
var relationKey = (relation2) => {
|
|
932
892
|
const normalized = normalizeRelation(relation2);
|
|
933
|
-
return
|
|
893
|
+
return secondaryKey(normalized.kind, normalized.direction);
|
|
934
894
|
};
|
|
935
895
|
var relationFromKey = (encoded) => {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
S: void 0,
|
|
941
|
-
A: [
|
|
942
|
-
"separatorIndex > 0 && separatorIndex < encoded.length - 1",
|
|
943
|
-
"`Invalid relation key: ${encoded}`"
|
|
944
|
-
]
|
|
945
|
-
});
|
|
946
|
-
const kind = encoded.slice(0, separatorIndex);
|
|
947
|
-
const directionRaw = encoded.slice(separatorIndex + 1);
|
|
948
|
-
invariant(directionRaw === "outbound" || directionRaw === "inbound", `Invalid relation direction: ${directionRaw}`, {
|
|
949
|
-
F: __dxlog_file,
|
|
950
|
-
L: 1224,
|
|
951
|
-
S: void 0,
|
|
952
|
-
A: [
|
|
953
|
-
"directionRaw === 'outbound' || directionRaw === 'inbound'",
|
|
954
|
-
"`Invalid relation direction: ${directionRaw}`"
|
|
955
|
-
]
|
|
956
|
-
});
|
|
896
|
+
const parts = secondaryParts(encoded);
|
|
897
|
+
invariant2(parts.length === 2 && parts[0].length > 0 && parts[1].length > 0, `Invalid relation key: ${encoded}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 894, S: void 0, A: ["parts.length === 2 && parts[0].length > 0 && parts[1].length > 0", "`Invalid relation key: ${encoded}`"] });
|
|
898
|
+
const [kind, directionRaw] = parts;
|
|
899
|
+
invariant2(directionRaw === "outbound" || directionRaw === "inbound", `Invalid relation direction: ${directionRaw}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 896, S: void 0, A: ["directionRaw === 'outbound' || directionRaw === 'inbound'", "`Invalid relation direction: ${directionRaw}`"] });
|
|
957
900
|
return relation(kind, directionRaw);
|
|
958
901
|
};
|
|
959
|
-
var connectionKey = (id, relation2) =>
|
|
902
|
+
var connectionKey = (id, relation2) => primaryKey(id, relationKey(relation2));
|
|
960
903
|
var relationFromConnectionKey = (key) => {
|
|
961
|
-
const
|
|
962
|
-
|
|
963
|
-
F: __dxlog_file,
|
|
964
|
-
L: 1233,
|
|
965
|
-
S: void 0,
|
|
966
|
-
A: [
|
|
967
|
-
"separatorIndex > 0 && separatorIndex < key.length - 1",
|
|
968
|
-
"`Invalid connection key: ${key}`"
|
|
969
|
-
]
|
|
970
|
-
});
|
|
971
|
-
const id = key.slice(0, separatorIndex);
|
|
972
|
-
const encodedRelation = key.slice(separatorIndex + 1);
|
|
904
|
+
const [id, encodedRelation] = primaryParts(key);
|
|
905
|
+
invariant2(id && encodedRelation, `Invalid connection key: ${key}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 902, S: void 0, A: ["id && encodedRelation", "`Invalid connection key: ${key}`"] });
|
|
973
906
|
return {
|
|
974
907
|
id,
|
|
975
908
|
relation: relationFromKey(encodedRelation)
|
|
@@ -980,34 +913,6 @@ var inverseRelation = (relation2) => {
|
|
|
980
913
|
return relation(normalized.kind, normalized.direction === "outbound" ? "inbound" : "outbound");
|
|
981
914
|
};
|
|
982
915
|
|
|
983
|
-
// src/graph-builder.ts
|
|
984
|
-
var graph_builder_exports = {};
|
|
985
|
-
__export(graph_builder_exports, {
|
|
986
|
-
GraphBuilderTypeId: () => GraphBuilderTypeId,
|
|
987
|
-
addExtension: () => addExtension,
|
|
988
|
-
createConnector: () => createConnector,
|
|
989
|
-
createExtension: () => createExtension,
|
|
990
|
-
createExtensionRaw: () => createExtensionRaw,
|
|
991
|
-
createTypeExtension: () => createTypeExtension,
|
|
992
|
-
destroy: () => destroy,
|
|
993
|
-
explore: () => explore,
|
|
994
|
-
flattenExtensions: () => flattenExtensions,
|
|
995
|
-
flush: () => flush,
|
|
996
|
-
from: () => from,
|
|
997
|
-
make: () => make2,
|
|
998
|
-
removeExtension: () => removeExtension
|
|
999
|
-
});
|
|
1000
|
-
import { Atom as Atom3, Registry as Registry2 } from "@effect-atom/atom-react";
|
|
1001
|
-
import * as Array2 from "effect/Array";
|
|
1002
|
-
import * as Effect from "effect/Effect";
|
|
1003
|
-
import * as Function2 from "effect/Function";
|
|
1004
|
-
import * as Option3 from "effect/Option";
|
|
1005
|
-
import * as Pipeable2 from "effect/Pipeable";
|
|
1006
|
-
import * as Record2 from "effect/Record";
|
|
1007
|
-
import { scheduleTask, yieldOrContinue } from "main-thread-scheduling";
|
|
1008
|
-
import { log as log2 } from "@dxos/log";
|
|
1009
|
-
import { byPosition, getDebugName, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
1010
|
-
|
|
1011
916
|
// src/node-matcher.ts
|
|
1012
917
|
var node_matcher_exports = {};
|
|
1013
918
|
__export(node_matcher_exports, {
|
|
@@ -1030,17 +935,23 @@ var whenNodeType = (type) => (node) => node.type === type ? Option2.some(node) :
|
|
|
1030
935
|
var whenEchoType = (type) => (node) => Obj.instanceOf(type, node.data) ? Option2.some(node.data) : Option2.none();
|
|
1031
936
|
var whenEchoObject = (node) => Obj.isObject(node.data) ? Option2.some(node.data) : Option2.none();
|
|
1032
937
|
var whenAll = (...matchers) => (node) => {
|
|
938
|
+
let first = Option2.none();
|
|
1033
939
|
for (const candidate of matchers) {
|
|
1034
|
-
|
|
940
|
+
const result = candidate(node);
|
|
941
|
+
if (Option2.isNone(result)) {
|
|
1035
942
|
return Option2.none();
|
|
1036
943
|
}
|
|
944
|
+
if (Option2.isNone(first)) {
|
|
945
|
+
first = result;
|
|
946
|
+
}
|
|
1037
947
|
}
|
|
1038
|
-
return
|
|
948
|
+
return first;
|
|
1039
949
|
};
|
|
1040
950
|
var whenAny = (...matchers) => (node) => {
|
|
1041
951
|
for (const candidate of matchers) {
|
|
1042
|
-
|
|
1043
|
-
|
|
952
|
+
const result = candidate(node);
|
|
953
|
+
if (Option2.isSome(result)) {
|
|
954
|
+
return result;
|
|
1044
955
|
}
|
|
1045
956
|
}
|
|
1046
957
|
return Option2.none();
|
|
@@ -1050,7 +961,33 @@ var whenEchoObjectMatches = (node) => Obj.isObject(node.data) ? Option2.some(nod
|
|
|
1050
961
|
var whenNot = (matcher) => (node) => Option2.isNone(matcher(node)) ? Option2.some(node) : Option2.none();
|
|
1051
962
|
|
|
1052
963
|
// src/graph-builder.ts
|
|
1053
|
-
var
|
|
964
|
+
var graph_builder_exports = {};
|
|
965
|
+
__export(graph_builder_exports, {
|
|
966
|
+
GraphBuilderTypeId: () => GraphBuilderTypeId,
|
|
967
|
+
addExtension: () => addExtension,
|
|
968
|
+
createConnector: () => createConnector,
|
|
969
|
+
createExtension: () => createExtension,
|
|
970
|
+
createExtensionRaw: () => createExtensionRaw,
|
|
971
|
+
createTypeExtension: () => createTypeExtension,
|
|
972
|
+
destroy: () => destroy,
|
|
973
|
+
explore: () => explore,
|
|
974
|
+
flattenExtensions: () => flattenExtensions,
|
|
975
|
+
flush: () => flush,
|
|
976
|
+
from: () => from,
|
|
977
|
+
make: () => make3,
|
|
978
|
+
removeExtension: () => removeExtension
|
|
979
|
+
});
|
|
980
|
+
import { Atom as Atom2, Registry as Registry2 } from "@effect-atom/atom-react";
|
|
981
|
+
import * as Array2 from "effect/Array";
|
|
982
|
+
import * as Effect from "effect/Effect";
|
|
983
|
+
import * as Function2 from "effect/Function";
|
|
984
|
+
import * as Option3 from "effect/Option";
|
|
985
|
+
import * as Pipeable2 from "effect/Pipeable";
|
|
986
|
+
import * as Record2 from "effect/Record";
|
|
987
|
+
import { log as log2 } from "@dxos/log";
|
|
988
|
+
import { byPosition, getDebugName, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
989
|
+
import { scheduleTask, yieldOrContinue } from "#scheduler";
|
|
990
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph-builder.ts";
|
|
1054
991
|
var GraphBuilderTypeId = /* @__PURE__ */ Symbol.for("@dxos/app-graph/GraphBuilder");
|
|
1055
992
|
var GraphBuilderImpl = class {
|
|
1056
993
|
[GraphBuilderTypeId] = GraphBuilderTypeId;
|
|
@@ -1058,19 +995,31 @@ var GraphBuilderImpl = class {
|
|
|
1058
995
|
return Pipeable2.pipeArguments(this, arguments);
|
|
1059
996
|
}
|
|
1060
997
|
// TODO(wittjosiah): Use Context.
|
|
998
|
+
/** Active subscriptions keyed by composite ID, cleaned up on node removal. */
|
|
1061
999
|
_subscriptions = /* @__PURE__ */ new Map();
|
|
1000
|
+
/** Connector updates pending flush, keyed by connector key. */
|
|
1062
1001
|
_dirtyConnectors = /* @__PURE__ */ new Map();
|
|
1002
|
+
/** Last-flushed node IDs per connector key, used for edge removal on update. */
|
|
1063
1003
|
_connectorPrevious = /* @__PURE__ */ new Map();
|
|
1004
|
+
/** All inline-descendant IDs per connector key, used to remove stale inline nodes on update. */
|
|
1005
|
+
_connectorPreviousInlineIds = /* @__PURE__ */ new Map();
|
|
1006
|
+
/** Last-flushed node args per connector key, used for change detection. */
|
|
1064
1007
|
_connectorPreviousArgs = /* @__PURE__ */ new Map();
|
|
1008
|
+
/** Whether a dirty-flush task is already scheduled. */
|
|
1065
1009
|
_flushScheduled = false;
|
|
1010
|
+
/** Resolves when the current flush completes. */
|
|
1066
1011
|
_flushPromise = Promise.resolve();
|
|
1067
|
-
|
|
1012
|
+
/** Registered builder extensions keyed by extension ID. */
|
|
1013
|
+
_extensions = Atom2.make(Record2.empty()).pipe(Atom2.keepAlive, Atom2.withLabel("graph-builder:extensions"));
|
|
1014
|
+
/** Triggers signalling that a node's resolver has fired at least once. */
|
|
1068
1015
|
_initialized = {};
|
|
1016
|
+
/** Shared atom registry for reactive subscriptions. */
|
|
1069
1017
|
_registry;
|
|
1018
|
+
/** Backing graph with internal accessors for node atoms and construction. */
|
|
1070
1019
|
_graph;
|
|
1071
1020
|
constructor({ registry, ...params } = {}) {
|
|
1072
1021
|
this._registry = registry ?? Registry2.make();
|
|
1073
|
-
const graph =
|
|
1022
|
+
const graph = make2({
|
|
1074
1023
|
...params,
|
|
1075
1024
|
registry: this._registry,
|
|
1076
1025
|
onExpand: (id, relation2) => this._onExpand(id, relation2),
|
|
@@ -1092,6 +1041,11 @@ var GraphBuilderImpl = class {
|
|
|
1092
1041
|
const removed = previous.filter((pid) => !ids.includes(pid));
|
|
1093
1042
|
this._connectorPrevious.set(key, ids);
|
|
1094
1043
|
this._connectorPreviousArgs.set(key, nodes);
|
|
1044
|
+
const currentInlineIds = collectAllInlineIds(nodes);
|
|
1045
|
+
const previousInlineIds = this._connectorPreviousInlineIds.get(key) ?? [];
|
|
1046
|
+
const staleInlineIds = previousInlineIds.filter((pid) => !currentInlineIds.includes(pid));
|
|
1047
|
+
this._connectorPreviousInlineIds.set(key, currentInlineIds);
|
|
1048
|
+
removeNodes(this._graph, staleInlineIds, true);
|
|
1095
1049
|
removeEdges(this._graph, removed.map((target) => ({
|
|
1096
1050
|
source: id,
|
|
1097
1051
|
target,
|
|
@@ -1120,7 +1074,7 @@ var GraphBuilderImpl = class {
|
|
|
1120
1074
|
...this._dirtyConnectors.entries()
|
|
1121
1075
|
];
|
|
1122
1076
|
this._dirtyConnectors.clear();
|
|
1123
|
-
|
|
1077
|
+
Atom2.batch(() => {
|
|
1124
1078
|
for (const [key, { nodes, previous }] of entries) {
|
|
1125
1079
|
this._applyConnectorUpdate(key, nodes, previous);
|
|
1126
1080
|
}
|
|
@@ -1131,13 +1085,13 @@ var GraphBuilderImpl = class {
|
|
|
1131
1085
|
});
|
|
1132
1086
|
}
|
|
1133
1087
|
}
|
|
1134
|
-
_resolvers =
|
|
1135
|
-
return
|
|
1088
|
+
_resolvers = Atom2.family((id) => {
|
|
1089
|
+
return Atom2.make((get2) => {
|
|
1136
1090
|
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);
|
|
1137
1091
|
});
|
|
1138
1092
|
});
|
|
1139
|
-
_connectors =
|
|
1140
|
-
return
|
|
1093
|
+
_connectors = Atom2.family((key) => {
|
|
1094
|
+
return Atom2.make((get2) => {
|
|
1141
1095
|
const { id, relation: relation2 } = relationFromConnectorKey(key);
|
|
1142
1096
|
const node = this._graph.node(id);
|
|
1143
1097
|
const sourceNode = Option3.getOrElse(get2(node), () => void 0);
|
|
@@ -1151,19 +1105,14 @@ var GraphBuilderImpl = class {
|
|
|
1151
1105
|
nodes.push(...result);
|
|
1152
1106
|
}
|
|
1153
1107
|
return nodes;
|
|
1154
|
-
}).pipe(
|
|
1108
|
+
}).pipe(Atom2.withLabel(`graph-builder:connectors:${key}`));
|
|
1155
1109
|
});
|
|
1156
1110
|
_onExpand(id, relation2) {
|
|
1157
1111
|
log2("onExpand", {
|
|
1158
1112
|
id,
|
|
1159
1113
|
relation: relation2,
|
|
1160
1114
|
registry: getDebugName(this._registry)
|
|
1161
|
-
}, {
|
|
1162
|
-
F: __dxlog_file2,
|
|
1163
|
-
L: 251,
|
|
1164
|
-
S: this,
|
|
1165
|
-
C: (f, a) => f(...a)
|
|
1166
|
-
});
|
|
1115
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 136, S: this });
|
|
1167
1116
|
this._expandRelation(id, relation2);
|
|
1168
1117
|
if (relation2.kind === "child" && relation2.direction === "outbound") {
|
|
1169
1118
|
expand(this._graph, id, "action");
|
|
@@ -1172,7 +1121,8 @@ var GraphBuilderImpl = class {
|
|
|
1172
1121
|
_expandRelation(id, relation2) {
|
|
1173
1122
|
const key = connectorKey(id, relation2);
|
|
1174
1123
|
const connectors = this._connectors(key);
|
|
1175
|
-
const cancel = this._registry.subscribe(connectors, (
|
|
1124
|
+
const cancel = this._registry.subscribe(connectors, (rawNodes) => {
|
|
1125
|
+
const nodes = qualifyNodeArgs(id)(rawNodes);
|
|
1176
1126
|
const previous = this._connectorPrevious.get(key) ?? [];
|
|
1177
1127
|
const ids = nodes.map((n) => n.id);
|
|
1178
1128
|
if (ids.length === previous.length && ids.every((nodeId, idx) => nodeId === previous[idx])) {
|
|
@@ -1185,12 +1135,7 @@ var GraphBuilderImpl = class {
|
|
|
1185
1135
|
id,
|
|
1186
1136
|
relation: relation2,
|
|
1187
1137
|
ids
|
|
1188
|
-
}, {
|
|
1189
|
-
F: __dxlog_file2,
|
|
1190
|
-
L: 277,
|
|
1191
|
-
S: this,
|
|
1192
|
-
C: (f, a) => f(...a)
|
|
1193
|
-
});
|
|
1138
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 160, S: this });
|
|
1194
1139
|
this._dirtyConnectors.set(key, {
|
|
1195
1140
|
nodes,
|
|
1196
1141
|
previous
|
|
@@ -1201,31 +1146,42 @@ var GraphBuilderImpl = class {
|
|
|
1201
1146
|
});
|
|
1202
1147
|
this._subscriptions.set(subscriptionKey(id, "expand", key), cancel);
|
|
1203
1148
|
}
|
|
1204
|
-
// TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?
|
|
1205
1149
|
async _onInitialize(id) {
|
|
1206
1150
|
log2("onInitialize", {
|
|
1207
1151
|
id
|
|
1208
|
-
}, {
|
|
1209
|
-
F: __dxlog_file2,
|
|
1210
|
-
L: 289,
|
|
1211
|
-
S: this,
|
|
1212
|
-
C: (f, a) => f(...a)
|
|
1213
|
-
});
|
|
1152
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 176, S: this });
|
|
1214
1153
|
const resolver = this._resolvers(id);
|
|
1215
1154
|
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
1216
1155
|
const trigger = this._initialized[id];
|
|
1156
|
+
const connectorOwned = [
|
|
1157
|
+
...this._connectorPrevious.values()
|
|
1158
|
+
].some((ids) => ids.includes(id));
|
|
1217
1159
|
Option3.match(node, {
|
|
1218
1160
|
onSome: (node2) => {
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1161
|
+
if (!connectorOwned) {
|
|
1162
|
+
addNodes(this._graph, [
|
|
1163
|
+
node2
|
|
1164
|
+
]);
|
|
1165
|
+
const parentId = getParentId(id);
|
|
1166
|
+
if (parentId) {
|
|
1167
|
+
addEdges(this._graph, [
|
|
1168
|
+
{
|
|
1169
|
+
source: parentId,
|
|
1170
|
+
target: id,
|
|
1171
|
+
relation: "child"
|
|
1172
|
+
}
|
|
1173
|
+
]);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1222
1176
|
trigger?.wake();
|
|
1223
1177
|
},
|
|
1224
1178
|
onNone: () => {
|
|
1225
1179
|
trigger?.wake();
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1180
|
+
if (!connectorOwned) {
|
|
1181
|
+
removeNodes(this._graph, [
|
|
1182
|
+
id
|
|
1183
|
+
]);
|
|
1184
|
+
}
|
|
1229
1185
|
}
|
|
1230
1186
|
});
|
|
1231
1187
|
}, {
|
|
@@ -1234,26 +1190,25 @@ var GraphBuilderImpl = class {
|
|
|
1234
1190
|
this._subscriptions.set(subscriptionKey(id, "init"), cancel);
|
|
1235
1191
|
}
|
|
1236
1192
|
_onRemoveNode(id) {
|
|
1237
|
-
const prefix = `${id}${Separators.primary}`;
|
|
1238
1193
|
for (const [key, cleanup] of this._subscriptions) {
|
|
1239
|
-
if (key
|
|
1194
|
+
if (primaryParts(key)[0] === id) {
|
|
1240
1195
|
cleanup();
|
|
1241
1196
|
this._subscriptions.delete(key);
|
|
1242
1197
|
}
|
|
1243
1198
|
}
|
|
1244
1199
|
}
|
|
1245
1200
|
};
|
|
1246
|
-
var
|
|
1201
|
+
var make3 = (params) => {
|
|
1247
1202
|
return new GraphBuilderImpl(params);
|
|
1248
1203
|
};
|
|
1249
1204
|
var from = (pickle, registry) => {
|
|
1250
1205
|
if (!pickle) {
|
|
1251
|
-
return
|
|
1206
|
+
return make3({
|
|
1252
1207
|
registry
|
|
1253
1208
|
});
|
|
1254
1209
|
}
|
|
1255
1210
|
const { nodes, edges } = JSON.parse(pickle);
|
|
1256
|
-
return
|
|
1211
|
+
return make3({
|
|
1257
1212
|
nodes,
|
|
1258
1213
|
edges,
|
|
1259
1214
|
registry
|
|
@@ -1306,7 +1261,7 @@ var exploreImpl = async (builder, options, path = []) => {
|
|
|
1306
1261
|
if (shouldContinue === false) {
|
|
1307
1262
|
return;
|
|
1308
1263
|
}
|
|
1309
|
-
const nodes =
|
|
1264
|
+
const nodes = Function2.pipe(internal._registry.get(internal._extensions), Record2.values, Array2.map((extension) => extension.connector), Array2.filter(isNonNullable2), Array2.flatMap((connector) => registry.get(connector(internal._graph.node(source)))), qualifyNodeArgs(source));
|
|
1310
1265
|
await Promise.all(nodes.map((nodeArg) => {
|
|
1311
1266
|
registry.set(internal._graph._node(nodeArg.id), internal._graph._constructNode(nodeArg));
|
|
1312
1267
|
return exploreImpl(builder, {
|
|
@@ -1352,13 +1307,13 @@ var flush = (builder) => {
|
|
|
1352
1307
|
return builder._flushPromise;
|
|
1353
1308
|
};
|
|
1354
1309
|
var createExtensionRaw = (extension) => {
|
|
1355
|
-
const { id, position
|
|
1310
|
+
const { id, position, relation: relation2 = "child", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
1356
1311
|
const normalizedRelation = normalizeRelation(relation2);
|
|
1357
1312
|
const getId = (key) => `${id}/${key}`;
|
|
1358
|
-
const resolver = _resolver &&
|
|
1359
|
-
const connector = _connector &&
|
|
1360
|
-
const actionGroups = _actionGroups &&
|
|
1361
|
-
const actions = _actions &&
|
|
1313
|
+
const resolver = _resolver && Atom2.family((id2) => _resolver(id2).pipe(Atom2.withLabel(`graph-builder:_resolver:${id2}`)));
|
|
1314
|
+
const connector = _connector && Atom2.family((node) => _connector(node).pipe(Atom2.withLabel(`graph-builder:_connector:${id}`)));
|
|
1315
|
+
const actionGroups = _actionGroups && Atom2.family((node) => _actionGroups(node).pipe(Atom2.withLabel(`graph-builder:_actionGroups:${id}`)));
|
|
1316
|
+
const actions = _actions && Atom2.family((node) => _actions(node).pipe(Atom2.withLabel(`graph-builder:_actions:${id}`)));
|
|
1362
1317
|
return [
|
|
1363
1318
|
resolver ? {
|
|
1364
1319
|
id: getId("resolver"),
|
|
@@ -1369,7 +1324,7 @@ var createExtensionRaw = (extension) => {
|
|
|
1369
1324
|
id: getId("connector"),
|
|
1370
1325
|
position,
|
|
1371
1326
|
relation: normalizedRelation,
|
|
1372
|
-
connector:
|
|
1327
|
+
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
1373
1328
|
try {
|
|
1374
1329
|
return get2(connector(node));
|
|
1375
1330
|
} catch (error) {
|
|
@@ -1377,21 +1332,16 @@ var createExtensionRaw = (extension) => {
|
|
|
1377
1332
|
id: getId("connector"),
|
|
1378
1333
|
node,
|
|
1379
1334
|
error
|
|
1380
|
-
}, {
|
|
1381
|
-
F: __dxlog_file2,
|
|
1382
|
-
L: 579,
|
|
1383
|
-
S: void 0,
|
|
1384
|
-
C: (f, a) => f(...a)
|
|
1385
|
-
});
|
|
1335
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 383, S: void 0 });
|
|
1386
1336
|
return [];
|
|
1387
1337
|
}
|
|
1388
|
-
}).pipe(
|
|
1338
|
+
}).pipe(Atom2.withLabel(`graph-builder:connector:${id}`)))
|
|
1389
1339
|
} : void 0,
|
|
1390
1340
|
actionGroups ? {
|
|
1391
1341
|
id: getId("actionGroups"),
|
|
1392
1342
|
position,
|
|
1393
1343
|
relation: actionRelation(),
|
|
1394
|
-
connector:
|
|
1344
|
+
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
1395
1345
|
try {
|
|
1396
1346
|
return get2(actionGroups(node)).map((arg) => ({
|
|
1397
1347
|
...arg,
|
|
@@ -1403,21 +1353,16 @@ var createExtensionRaw = (extension) => {
|
|
|
1403
1353
|
id: getId("actionGroups"),
|
|
1404
1354
|
node,
|
|
1405
1355
|
error
|
|
1406
|
-
}, {
|
|
1407
|
-
F: __dxlog_file2,
|
|
1408
|
-
L: 600,
|
|
1409
|
-
S: void 0,
|
|
1410
|
-
C: (f, a) => f(...a)
|
|
1411
|
-
});
|
|
1356
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 404, S: void 0 });
|
|
1412
1357
|
return [];
|
|
1413
1358
|
}
|
|
1414
|
-
}).pipe(
|
|
1359
|
+
}).pipe(Atom2.withLabel(`graph-builder:connector:actionGroups:${id}`)))
|
|
1415
1360
|
} : void 0,
|
|
1416
1361
|
actions ? {
|
|
1417
1362
|
id: getId("actions"),
|
|
1418
1363
|
position,
|
|
1419
1364
|
relation: actionRelation(),
|
|
1420
|
-
connector:
|
|
1365
|
+
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
1421
1366
|
try {
|
|
1422
1367
|
return get2(actions(node)).map((arg) => ({
|
|
1423
1368
|
...arg,
|
|
@@ -1428,15 +1373,10 @@ var createExtensionRaw = (extension) => {
|
|
|
1428
1373
|
id: getId("actions"),
|
|
1429
1374
|
node,
|
|
1430
1375
|
error
|
|
1431
|
-
}, {
|
|
1432
|
-
F: __dxlog_file2,
|
|
1433
|
-
L: 617,
|
|
1434
|
-
S: void 0,
|
|
1435
|
-
C: (f, a) => f(...a)
|
|
1436
|
-
});
|
|
1376
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 424, S: void 0 });
|
|
1437
1377
|
return [];
|
|
1438
1378
|
}
|
|
1439
|
-
}).pipe(
|
|
1379
|
+
}).pipe(Atom2.withLabel(`graph-builder:connector:actions:${id}`)))
|
|
1440
1380
|
} : void 0
|
|
1441
1381
|
].filter(isNonNullable2);
|
|
1442
1382
|
};
|
|
@@ -1445,24 +1385,19 @@ var runEffectSyncWithFallback = (effect, context2, extensionId, fallback) => {
|
|
|
1445
1385
|
log2.warn("Extension failed", {
|
|
1446
1386
|
extension: extensionId,
|
|
1447
1387
|
error
|
|
1448
|
-
}, {
|
|
1449
|
-
F: __dxlog_file2,
|
|
1450
|
-
L: 660,
|
|
1451
|
-
S: void 0,
|
|
1452
|
-
C: (f, a) => f(...a)
|
|
1453
|
-
});
|
|
1388
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 441, S: void 0 });
|
|
1454
1389
|
return Effect.succeed(fallback);
|
|
1455
1390
|
})));
|
|
1456
1391
|
};
|
|
1457
1392
|
var createExtension = (options) => Effect.map(Effect.context(), (context2) => {
|
|
1458
1393
|
const { id, match: match3, actions, connector, resolver, relation: relation2, position } = options;
|
|
1459
1394
|
const connectorExtension = connector ? createConnectorWithRuntime(id, match3, connector, context2) : void 0;
|
|
1460
|
-
const actionsExtension = actions ? (node) =>
|
|
1395
|
+
const actionsExtension = actions ? (node) => Atom2.make((get2) => Function2.pipe(get2(node), Option3.flatMap(match3), Option3.map((matched) => runEffectSyncWithFallback(actions(matched, get2), context2, id, []).map((action) => ({
|
|
1461
1396
|
...action,
|
|
1462
1397
|
// Attach captured context for action execution.
|
|
1463
1398
|
_actionContext: context2
|
|
1464
1399
|
}))), Option3.getOrElse(() => []))) : void 0;
|
|
1465
|
-
const resolverExtension = resolver ? (nodeId) =>
|
|
1400
|
+
const resolverExtension = resolver ? (nodeId) => Atom2.make((get2) => runEffectSyncWithFallback(resolver(nodeId, get2), context2, id, null) ?? null) : void 0;
|
|
1466
1401
|
return createExtensionRaw({
|
|
1467
1402
|
id,
|
|
1468
1403
|
relation: relation2,
|
|
@@ -1473,10 +1408,10 @@ var createExtension = (options) => Effect.map(Effect.context(), (context2) => {
|
|
|
1473
1408
|
});
|
|
1474
1409
|
});
|
|
1475
1410
|
var createConnector = (matcher, factory) => {
|
|
1476
|
-
return (node) =>
|
|
1411
|
+
return (node) => Atom2.make((get2) => Function2.pipe(get2(node), Option3.flatMap(matcher), Option3.map((data) => factory(data, get2)), Option3.getOrElse(() => [])));
|
|
1477
1412
|
};
|
|
1478
1413
|
var createConnectorWithRuntime = (extensionId, matcher, factory, context2) => {
|
|
1479
|
-
return (node) =>
|
|
1414
|
+
return (node) => Atom2.make((get2) => Function2.pipe(get2(node), Option3.flatMap(matcher), Option3.map((data) => runEffectSyncWithFallback(factory(data, get2), context2, extensionId, [])), Option3.getOrElse(() => [])));
|
|
1480
1415
|
};
|
|
1481
1416
|
var createTypeExtension = (options) => {
|
|
1482
1417
|
const { id, type, actions, connector, relation: relation2, position } = options;
|
|
@@ -1489,16 +1424,28 @@ var createTypeExtension = (options) => {
|
|
|
1489
1424
|
position
|
|
1490
1425
|
});
|
|
1491
1426
|
};
|
|
1492
|
-
var
|
|
1427
|
+
var qualifyNodeArgs = (parentId) => (nodes) => nodes.map((node) => {
|
|
1428
|
+
validateSegmentId(node.id);
|
|
1429
|
+
const qualified = qualifyId(parentId, node.id);
|
|
1430
|
+
return {
|
|
1431
|
+
...node,
|
|
1432
|
+
id: qualified,
|
|
1433
|
+
nodes: node.nodes ? qualifyNodeArgs(qualified)(node.nodes) : void 0
|
|
1434
|
+
};
|
|
1435
|
+
});
|
|
1436
|
+
var collectAllInlineIds = (nodes) => nodes.flatMap((node) => node.nodes ? [
|
|
1437
|
+
...node.nodes.map((child) => child.id),
|
|
1438
|
+
...collectAllInlineIds(node.nodes)
|
|
1439
|
+
] : []);
|
|
1440
|
+
var connectorKey = (id, relation2) => primaryKey(id, relationKey(relation2));
|
|
1493
1441
|
var relationFromConnectorKey = (key) => {
|
|
1494
|
-
const
|
|
1495
|
-
const id = key.slice(0, separatorIndex);
|
|
1442
|
+
const [id, encodedRelation] = primaryParts(key);
|
|
1496
1443
|
return {
|
|
1497
1444
|
id,
|
|
1498
|
-
relation: relationFromKey(
|
|
1445
|
+
relation: relationFromKey(encodedRelation)
|
|
1499
1446
|
};
|
|
1500
1447
|
};
|
|
1501
|
-
var subscriptionKey = (id, kind, detail) => detail != null ?
|
|
1448
|
+
var subscriptionKey = (id, kind, detail) => detail != null ? primaryKey(id, kind, detail) : primaryKey(id, kind);
|
|
1502
1449
|
var flattenExtensions = (extension, acc = []) => {
|
|
1503
1450
|
if (Array2.isArray(extension)) {
|
|
1504
1451
|
return [
|
|
@@ -1512,11 +1459,19 @@ var flattenExtensions = (extension, acc = []) => {
|
|
|
1512
1459
|
];
|
|
1513
1460
|
}
|
|
1514
1461
|
};
|
|
1462
|
+
|
|
1515
1463
|
export {
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1464
|
+
node_exports,
|
|
1465
|
+
qualifyId,
|
|
1466
|
+
getParentId,
|
|
1467
|
+
getSegmentId,
|
|
1468
|
+
getNode,
|
|
1469
|
+
expand,
|
|
1470
|
+
graph_exports,
|
|
1471
|
+
node_matcher_exports,
|
|
1472
|
+
make3 as make,
|
|
1473
|
+
addExtension,
|
|
1474
|
+
flush,
|
|
1475
|
+
graph_builder_exports
|
|
1521
1476
|
};
|
|
1522
|
-
//# sourceMappingURL=
|
|
1477
|
+
//# sourceMappingURL=chunk-32XXJE6M.mjs.map
|