@dxos/app-graph 0.8.4-main.ef1bc66f44 → 0.8.4-main.f466a3d56e
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} +564 -384
- 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 +13 -9
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +13 -17
- 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 +46 -20
- package/dist/types/src/node-matcher.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +21 -5
- 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 +40 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +38 -27
- package/src/graph-builder.test.ts +695 -102
- package/src/graph-builder.ts +223 -76
- package/src/graph.test.ts +187 -52
- package/src/graph.ts +177 -98
- package/src/index.ts +1 -0
- package/src/node-matcher.ts +61 -31
- package/src/node.ts +46 -5
- package/src/scheduler.browser.ts +5 -0
- package/src/scheduler.ts +17 -0
- package/src/stories/EchoGraph.stories.tsx +94 -66
- package/src/stories/Tree.tsx +1 -1
- package/src/testing/index.ts +5 -0
- package/src/testing/setup-graph-builder.ts +41 -0
- package/src/util.ts +101 -0
- 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 -1298
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
|
@@ -1,24 +1,99 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-J5LGTIGS.mjs";
|
|
6
4
|
|
|
7
|
-
// src/
|
|
8
|
-
var
|
|
9
|
-
__export(
|
|
10
|
-
|
|
5
|
+
// src/node.ts
|
|
6
|
+
var node_exports = {};
|
|
7
|
+
__export(node_exports, {
|
|
8
|
+
ActionGroupType: () => ActionGroupType,
|
|
9
|
+
ActionType: () => ActionType,
|
|
10
|
+
RootId: () => RootId,
|
|
11
|
+
RootType: () => RootType,
|
|
12
|
+
actionGroupSymbol: () => actionGroupSymbol,
|
|
13
|
+
actionRelation: () => actionRelation,
|
|
14
|
+
childRelation: () => childRelation,
|
|
15
|
+
isAction: () => isAction,
|
|
16
|
+
isActionGroup: () => isActionGroup,
|
|
17
|
+
isActionLike: () => isActionLike,
|
|
18
|
+
isGraphNode: () => isGraphNode,
|
|
19
|
+
make: () => make,
|
|
20
|
+
makeAction: () => makeAction,
|
|
21
|
+
makeActionGroup: () => makeActionGroup,
|
|
22
|
+
relation: () => relation
|
|
11
23
|
});
|
|
12
|
-
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
var RootId = "root";
|
|
25
|
+
var RootType = "org.dxos.type.graphRoot";
|
|
26
|
+
var ActionType = "org.dxos.type.graphAction";
|
|
27
|
+
var ActionGroupType = "org.dxos.type.graphActionGroup";
|
|
28
|
+
var relation = (kind, direction = "outbound") => ({
|
|
29
|
+
kind,
|
|
30
|
+
direction
|
|
31
|
+
});
|
|
32
|
+
var childRelation = (direction = "outbound") => relation("child", direction);
|
|
33
|
+
var actionRelation = (direction = "outbound") => relation("action", direction);
|
|
34
|
+
var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
|
|
35
|
+
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" && data.type === ActionType : false;
|
|
36
|
+
var actionGroupSymbol = /* @__PURE__ */ Symbol("ActionGroup");
|
|
37
|
+
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ActionGroupType : false;
|
|
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
|
|
19
48
|
});
|
|
20
|
-
|
|
21
|
-
|
|
49
|
+
|
|
50
|
+
// src/util.ts
|
|
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);
|
|
60
|
+
var normalizeRelation = (relation2) => relation2 == null ? childRelation() : typeof relation2 === "string" ? relation(relation2) : relation2;
|
|
61
|
+
var shallowEqual = (a, b) => {
|
|
62
|
+
if (a === b) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (a == null || b == null || typeof a !== "object" || typeof b !== "object") {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const keysA = Object.keys(a);
|
|
69
|
+
const keysB = Object.keys(b);
|
|
70
|
+
if (keysA.length !== keysB.length) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
return keysA.every((k) => a[k] === b[k]);
|
|
74
|
+
};
|
|
75
|
+
var nodeArgsUnchanged = (prev, next) => {
|
|
76
|
+
if (prev.length !== next.length) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return prev.every((prevNode, idx) => {
|
|
80
|
+
const nextNode = next[idx];
|
|
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 ?? []);
|
|
82
|
+
});
|
|
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;
|
|
22
97
|
};
|
|
23
98
|
|
|
24
99
|
// src/graph.ts
|
|
@@ -40,7 +115,9 @@ __export(graph_exports, {
|
|
|
40
115
|
getPath: () => getPath,
|
|
41
116
|
getRoot: () => getRoot,
|
|
42
117
|
initialize: () => initialize,
|
|
43
|
-
make: () =>
|
|
118
|
+
make: () => make2,
|
|
119
|
+
relationFromKey: () => relationFromKey,
|
|
120
|
+
relationKey: () => relationKey,
|
|
44
121
|
removeEdge: () => removeEdge,
|
|
45
122
|
removeEdges: () => removeEdges,
|
|
46
123
|
removeNode: () => removeNode,
|
|
@@ -50,58 +127,25 @@ __export(graph_exports, {
|
|
|
50
127
|
traverse: () => traverse,
|
|
51
128
|
waitForPath: () => waitForPath
|
|
52
129
|
});
|
|
53
|
-
import { Atom
|
|
130
|
+
import { Atom, Registry } from "@effect-atom/atom-react";
|
|
54
131
|
import * as Function from "effect/Function";
|
|
55
132
|
import * as Option from "effect/Option";
|
|
56
133
|
import * as Pipeable from "effect/Pipeable";
|
|
57
134
|
import * as Record from "effect/Record";
|
|
58
135
|
import { Event, Trigger } from "@dxos/async";
|
|
59
136
|
import { todo } from "@dxos/debug";
|
|
60
|
-
import { invariant } from "@dxos/invariant";
|
|
137
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
61
138
|
import { log } from "@dxos/log";
|
|
62
139
|
import { isNonNullable } from "@dxos/util";
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
var node_exports = {};
|
|
66
|
-
__export(node_exports, {
|
|
67
|
-
ActionGroupType: () => ActionGroupType,
|
|
68
|
-
ActionType: () => ActionType,
|
|
69
|
-
RootId: () => RootId,
|
|
70
|
-
RootType: () => RootType,
|
|
71
|
-
actionGroupSymbol: () => actionGroupSymbol,
|
|
72
|
-
isAction: () => isAction,
|
|
73
|
-
isActionGroup: () => isActionGroup,
|
|
74
|
-
isActionLike: () => isActionLike,
|
|
75
|
-
isGraphNode: () => isGraphNode
|
|
76
|
-
});
|
|
77
|
-
var RootId = "root";
|
|
78
|
-
var RootType = "dxos.org/type/GraphRoot";
|
|
79
|
-
var ActionType = "dxos.org/type/GraphAction";
|
|
80
|
-
var ActionGroupType = "dxos.org/type/GraphActionGroup";
|
|
81
|
-
var isGraphNode = (data) => data && typeof data === "object" && "id" in data && "properties" in data && data.properties ? typeof data.properties === "object" && "data" in data : false;
|
|
82
|
-
var isAction = (data) => isGraphNode(data) ? typeof data.data === "function" && data.type === ActionType : false;
|
|
83
|
-
var actionGroupSymbol = Symbol("ActionGroup");
|
|
84
|
-
var isActionGroup = (data) => isGraphNode(data) ? data.data === actionGroupSymbol && data.type === ActionGroupType : false;
|
|
85
|
-
var isActionLike = (data) => isAction(data) || isActionGroup(data);
|
|
86
|
-
|
|
87
|
-
// src/graph.ts
|
|
88
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
89
|
-
var graphSymbol = Symbol("graph");
|
|
140
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-graph/src/graph.ts";
|
|
141
|
+
var graphSymbol = /* @__PURE__ */ Symbol("graph");
|
|
90
142
|
var getGraph = (node) => {
|
|
91
143
|
const graph = node[graphSymbol];
|
|
92
|
-
|
|
93
|
-
F: __dxlog_file,
|
|
94
|
-
L: 32,
|
|
95
|
-
S: void 0,
|
|
96
|
-
A: [
|
|
97
|
-
"graph",
|
|
98
|
-
"'Node is not associated with a graph.'"
|
|
99
|
-
]
|
|
100
|
-
});
|
|
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.'"] });
|
|
101
145
|
return graph;
|
|
102
146
|
};
|
|
103
|
-
var GraphTypeId = Symbol.for("@dxos/app-graph/Graph");
|
|
104
|
-
var GraphKind = Symbol.for("@dxos/app-graph/GraphKind");
|
|
147
|
+
var GraphTypeId = /* @__PURE__ */ Symbol.for("@dxos/app-graph/Graph");
|
|
148
|
+
var GraphKind = /* @__PURE__ */ Symbol.for("@dxos/app-graph/GraphKind");
|
|
105
149
|
var GraphImpl = class {
|
|
106
150
|
[GraphTypeId] = GraphTypeId;
|
|
107
151
|
[GraphKind] = "writable";
|
|
@@ -114,6 +158,7 @@ var GraphImpl = class {
|
|
|
114
158
|
_onRemoveNode;
|
|
115
159
|
_registry;
|
|
116
160
|
_expanded = Record.empty();
|
|
161
|
+
_pendingExpands = /* @__PURE__ */ new Set();
|
|
117
162
|
_initialized = Record.empty();
|
|
118
163
|
_initialEdges = Record.empty();
|
|
119
164
|
_initialNodes = Record.fromEntries([
|
|
@@ -128,50 +173,46 @@ var GraphImpl = class {
|
|
|
128
173
|
]
|
|
129
174
|
]);
|
|
130
175
|
/** @internal */
|
|
131
|
-
_node =
|
|
176
|
+
_node = Atom.family((id) => {
|
|
132
177
|
const initial = Option.flatten(Record.get(this._initialNodes, id));
|
|
133
|
-
return
|
|
178
|
+
return Atom.make(initial).pipe(Atom.keepAlive, Atom.withLabel(`graph:node:${id}`));
|
|
134
179
|
});
|
|
135
|
-
_nodeOrThrow =
|
|
136
|
-
return
|
|
180
|
+
_nodeOrThrow = Atom.family((id) => {
|
|
181
|
+
return Atom.make((get2) => {
|
|
137
182
|
const node = get2(this._node(id));
|
|
138
|
-
|
|
139
|
-
F: __dxlog_file,
|
|
140
|
-
L: 174,
|
|
141
|
-
S: this,
|
|
142
|
-
A: [
|
|
143
|
-
"Option.isSome(node)",
|
|
144
|
-
"`Node not available: ${id}`"
|
|
145
|
-
]
|
|
146
|
-
});
|
|
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}`"] });
|
|
147
184
|
return node.value;
|
|
148
185
|
});
|
|
149
186
|
});
|
|
150
|
-
_edges =
|
|
151
|
-
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({
|
|
152
|
-
|
|
153
|
-
outbound: []
|
|
154
|
-
})));
|
|
155
|
-
return Atom2.make(initial).pipe(Atom2.keepAlive, Atom2.withLabel(`graph:edges:${id}`));
|
|
187
|
+
_edges = Atom.family((id) => {
|
|
188
|
+
const initial = Record.get(this._initialEdges, id).pipe(Option.getOrElse(() => ({})));
|
|
189
|
+
return Atom.make(initial).pipe(Atom.keepAlive, Atom.withLabel(`graph:edges:${id}`));
|
|
156
190
|
});
|
|
157
191
|
// NOTE: Currently the argument to the family needs to be referentially stable for the atom to be referentially stable.
|
|
158
192
|
// TODO(wittjosiah): Atom feature request, support for something akin to `ComplexMap` to allow for complex arguments.
|
|
159
|
-
_connections =
|
|
160
|
-
return
|
|
161
|
-
const
|
|
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
|
+
}
|
|
199
|
+
const { id, relation: relation2 } = relationFromConnectionKey(key);
|
|
162
200
|
const edges = get2(this._edges(id));
|
|
163
|
-
return edges[
|
|
164
|
-
}).pipe(
|
|
201
|
+
return (edges[relationKey(relation2)] ?? []).map((id2) => get2(this._node(id2))).filter(Option.isSome).map((o) => o.value);
|
|
202
|
+
}).pipe(Atom.withLabel(`graph:connections:${key}`));
|
|
165
203
|
});
|
|
166
|
-
_actions =
|
|
167
|
-
return
|
|
168
|
-
|
|
169
|
-
|
|
204
|
+
_actions = Atom.family((id) => {
|
|
205
|
+
return Atom.make((get2) => {
|
|
206
|
+
if (!id) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
return get2(this._connections(connectionKey(id, actionRelation())));
|
|
210
|
+
}).pipe(Atom.withLabel(`graph:actions:${id}`));
|
|
170
211
|
});
|
|
171
|
-
_json =
|
|
172
|
-
return
|
|
212
|
+
_json = Atom.family((id) => {
|
|
213
|
+
return Atom.make((get2) => {
|
|
173
214
|
const toJSON2 = (node, seen = []) => {
|
|
174
|
-
const nodes = get2(this._connections(
|
|
215
|
+
const nodes = get2(this._connections(connectionKey(node.id, "child")));
|
|
175
216
|
const obj = {
|
|
176
217
|
id: node.id,
|
|
177
218
|
type: node.type
|
|
@@ -192,7 +233,7 @@ var GraphImpl = class {
|
|
|
192
233
|
};
|
|
193
234
|
const root = get2(this._nodeOrThrow(id));
|
|
194
235
|
return toJSON2(root);
|
|
195
|
-
}).pipe(
|
|
236
|
+
}).pipe(Atom.withLabel(`graph:json:${id}`));
|
|
196
237
|
});
|
|
197
238
|
constructor({ registry, nodes, edges, onInitialize, onExpand, onRemoveNode } = {}) {
|
|
198
239
|
this._registry = registry ?? Registry.make();
|
|
@@ -219,8 +260,8 @@ var GraphImpl = class {
|
|
|
219
260
|
nodeOrThrow(id) {
|
|
220
261
|
return nodeOrThrowImpl(this, id);
|
|
221
262
|
}
|
|
222
|
-
connections(id,
|
|
223
|
-
return connectionsImpl(this, id,
|
|
263
|
+
connections(id, relation2) {
|
|
264
|
+
return connectionsImpl(this, id, relation2);
|
|
224
265
|
}
|
|
225
266
|
actions(id) {
|
|
226
267
|
return actionsImpl(this, id);
|
|
@@ -257,9 +298,9 @@ var nodeOrThrowImpl = (graph, id) => {
|
|
|
257
298
|
const internal = getInternal(graph);
|
|
258
299
|
return internal._nodeOrThrow(id);
|
|
259
300
|
};
|
|
260
|
-
var connectionsImpl = (graph, id,
|
|
301
|
+
var connectionsImpl = (graph, id, relation2) => {
|
|
261
302
|
const internal = getInternal(graph);
|
|
262
|
-
return internal._connections(
|
|
303
|
+
return internal._connections(connectionKey(id, relation2));
|
|
263
304
|
};
|
|
264
305
|
var actionsImpl = (graph, id) => {
|
|
265
306
|
const internal = getInternal(graph);
|
|
@@ -298,19 +339,20 @@ function getNodeOrThrow(graphOrId, id) {
|
|
|
298
339
|
function getRoot(graph) {
|
|
299
340
|
return getNodeOrThrowImpl(graph, RootId);
|
|
300
341
|
}
|
|
301
|
-
var getConnectionsImpl = (graph, id,
|
|
342
|
+
var getConnectionsImpl = (graph, id, relation2) => {
|
|
302
343
|
const internal = getInternal(graph);
|
|
303
|
-
return internal._registry.get(connectionsImpl(graph, id,
|
|
344
|
+
return internal._registry.get(connectionsImpl(graph, id, relation2));
|
|
304
345
|
};
|
|
305
|
-
function getConnections(graphOrId, idOrRelation,
|
|
346
|
+
function getConnections(graphOrId, idOrRelation, relation2) {
|
|
306
347
|
if (typeof graphOrId === "string") {
|
|
307
348
|
const id = graphOrId;
|
|
308
|
-
const rel =
|
|
349
|
+
const rel = idOrRelation;
|
|
309
350
|
return (graph) => getConnectionsImpl(graph, id, rel);
|
|
310
351
|
} else {
|
|
311
352
|
const graph = graphOrId;
|
|
312
353
|
const id = idOrRelation;
|
|
313
|
-
|
|
354
|
+
invariant2(relation2 !== void 0, "Relation is required.", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 272, S: this, A: ["relation !== undefined", "'Relation is required.'"] });
|
|
355
|
+
const rel = relation2;
|
|
314
356
|
return getConnectionsImpl(graph, id, rel);
|
|
315
357
|
}
|
|
316
358
|
}
|
|
@@ -341,7 +383,7 @@ function getEdges(graphOrId, id) {
|
|
|
341
383
|
}
|
|
342
384
|
}
|
|
343
385
|
var traverseImpl = (graph, options, path = []) => {
|
|
344
|
-
const { visitor, source = RootId, relation
|
|
386
|
+
const { visitor, source = RootId, relation: relation2 } = options;
|
|
345
387
|
if (path.includes(source)) {
|
|
346
388
|
return;
|
|
347
389
|
}
|
|
@@ -353,14 +395,25 @@ var traverseImpl = (graph, options, path = []) => {
|
|
|
353
395
|
if (shouldContinue === false) {
|
|
354
396
|
return;
|
|
355
397
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
+
}
|
|
364
417
|
};
|
|
365
418
|
function traverse(graphOrOptions, optionsOrPath, path) {
|
|
366
419
|
if (typeof graphOrOptions === "object" && "visitor" in graphOrOptions) {
|
|
@@ -379,6 +432,7 @@ var getPathImpl = (graph, params) => {
|
|
|
379
432
|
let found = Option.none();
|
|
380
433
|
traverseImpl(graph, {
|
|
381
434
|
source: node.id,
|
|
435
|
+
relation: "child",
|
|
382
436
|
visitor: (node2, path) => {
|
|
383
437
|
if (Option.isSome(found)) {
|
|
384
438
|
return false;
|
|
@@ -434,15 +488,10 @@ var initializeImpl = async (graph, id) => {
|
|
|
434
488
|
log("initialize", {
|
|
435
489
|
id,
|
|
436
490
|
initialized
|
|
437
|
-
}, {
|
|
438
|
-
F: __dxlog_file,
|
|
439
|
-
L: 661,
|
|
440
|
-
S: void 0,
|
|
441
|
-
C: (f, a) => f(...a)
|
|
442
|
-
});
|
|
491
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 431, S: void 0 });
|
|
443
492
|
if (!initialized) {
|
|
444
|
-
await internal._onInitialize?.(id);
|
|
445
493
|
Record.set(internal._initialized, id, true);
|
|
494
|
+
await internal._onInitialize?.(id);
|
|
446
495
|
}
|
|
447
496
|
return graph;
|
|
448
497
|
};
|
|
@@ -455,65 +504,79 @@ function initialize(graphOrId, id) {
|
|
|
455
504
|
return initializeImpl(graph, id);
|
|
456
505
|
}
|
|
457
506
|
}
|
|
458
|
-
var expandImpl = (graph, id,
|
|
507
|
+
var expandImpl = (graph, id, relation2) => {
|
|
459
508
|
const internal = getInternal(graph);
|
|
460
|
-
const
|
|
509
|
+
const normalizedRelation = normalizeRelation(relation2);
|
|
510
|
+
const key = primaryKey(id, relationKey(normalizedRelation));
|
|
511
|
+
const nodeOpt = internal._registry.get(internal._node(id));
|
|
512
|
+
if (Option.isNone(nodeOpt)) {
|
|
513
|
+
internal._pendingExpands.add(key);
|
|
514
|
+
log("expand", {
|
|
515
|
+
key,
|
|
516
|
+
deferred: true
|
|
517
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 463, S: void 0 });
|
|
518
|
+
return graph;
|
|
519
|
+
}
|
|
461
520
|
const expanded = Record.get(internal._expanded, key).pipe(Option.getOrElse(() => false));
|
|
462
521
|
log("expand", {
|
|
463
522
|
key,
|
|
464
523
|
expanded
|
|
465
|
-
}, {
|
|
466
|
-
F: __dxlog_file,
|
|
467
|
-
L: 702,
|
|
468
|
-
S: void 0,
|
|
469
|
-
C: (f, a) => f(...a)
|
|
470
|
-
});
|
|
524
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 470, S: void 0 });
|
|
471
525
|
if (!expanded) {
|
|
472
|
-
internal._onExpand?.(id, relation);
|
|
473
526
|
Record.set(internal._expanded, key, true);
|
|
527
|
+
internal._onExpand?.(id, normalizedRelation);
|
|
474
528
|
}
|
|
475
529
|
return graph;
|
|
476
530
|
};
|
|
477
|
-
function expand(graphOrId, idOrRelation,
|
|
531
|
+
function expand(graphOrId, idOrRelation, relation2) {
|
|
478
532
|
if (typeof graphOrId === "string") {
|
|
479
533
|
const id = graphOrId;
|
|
480
|
-
const rel =
|
|
534
|
+
const rel = idOrRelation;
|
|
481
535
|
return (graph) => expandImpl(graph, id, rel);
|
|
482
536
|
} else {
|
|
483
537
|
const graph = graphOrId;
|
|
484
538
|
const id = idOrRelation;
|
|
485
|
-
|
|
539
|
+
invariant2(relation2 !== void 0, "Relation is required.", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 490, S: this, A: ["relation !== undefined", "'Relation is required.'"] });
|
|
540
|
+
const rel = relation2;
|
|
486
541
|
return expandImpl(graph, id, rel);
|
|
487
542
|
}
|
|
488
543
|
}
|
|
489
|
-
var sortEdgesImpl = (graph, id,
|
|
544
|
+
var sortEdgesImpl = (graph, id, relation2, order) => {
|
|
490
545
|
const internal = getInternal(graph);
|
|
491
546
|
const edgesAtom = internal._edges(id);
|
|
492
547
|
const edges = internal._registry.get(edgesAtom);
|
|
493
|
-
const
|
|
494
|
-
const
|
|
495
|
-
|
|
548
|
+
const relationId = relationKey(relation2);
|
|
549
|
+
const current = edges[relationId] ?? [];
|
|
550
|
+
const unsorted = current.filter((id2) => !order.includes(id2));
|
|
551
|
+
const sorted = order.filter((id2) => current.includes(id2));
|
|
552
|
+
const newOrder = [
|
|
496
553
|
...sorted,
|
|
497
554
|
...unsorted
|
|
498
|
-
]
|
|
499
|
-
|
|
555
|
+
];
|
|
556
|
+
if (newOrder.length === current.length && newOrder.every((id2, i) => id2 === current[i])) {
|
|
557
|
+
return graph;
|
|
558
|
+
}
|
|
559
|
+
internal._registry.set(edgesAtom, {
|
|
560
|
+
...edges,
|
|
561
|
+
[relationId]: newOrder
|
|
562
|
+
});
|
|
500
563
|
return graph;
|
|
501
564
|
};
|
|
502
565
|
function sortEdges(graphOrId, idOrRelation, relationOrOrder, order) {
|
|
503
566
|
if (typeof graphOrId === "string") {
|
|
504
567
|
const id = graphOrId;
|
|
505
|
-
const
|
|
568
|
+
const relation2 = idOrRelation;
|
|
506
569
|
const order2 = relationOrOrder;
|
|
507
|
-
return (graph) => sortEdgesImpl(graph, id,
|
|
570
|
+
return (graph) => sortEdgesImpl(graph, id, relation2, order2);
|
|
508
571
|
} else {
|
|
509
572
|
const graph = graphOrId;
|
|
510
573
|
const id = idOrRelation;
|
|
511
|
-
const
|
|
512
|
-
return sortEdgesImpl(graph, id,
|
|
574
|
+
const relation2 = relationOrOrder;
|
|
575
|
+
return sortEdgesImpl(graph, id, relation2, order);
|
|
513
576
|
}
|
|
514
577
|
}
|
|
515
578
|
var addNodesImpl = (graph, nodes) => {
|
|
516
|
-
|
|
579
|
+
Atom.batch(() => {
|
|
517
580
|
nodes.map((node) => addNodeImpl(graph, node));
|
|
518
581
|
});
|
|
519
582
|
return graph;
|
|
@@ -535,31 +598,21 @@ var addNodeImpl = (graph, nodeArg) => {
|
|
|
535
598
|
Option.match(existingNode, {
|
|
536
599
|
onSome: (existing) => {
|
|
537
600
|
const typeChanged = existing.type !== type;
|
|
538
|
-
const dataChanged = existing.data
|
|
601
|
+
const dataChanged = !shallowEqual(existing.data, data);
|
|
539
602
|
const propertiesChanged = Object.keys(properties).some((key) => existing.properties[key] !== properties[key]);
|
|
540
603
|
log("existing node", {
|
|
541
604
|
id,
|
|
542
605
|
typeChanged,
|
|
543
606
|
dataChanged,
|
|
544
607
|
propertiesChanged
|
|
545
|
-
}, {
|
|
546
|
-
F: __dxlog_file,
|
|
547
|
-
L: 847,
|
|
548
|
-
S: void 0,
|
|
549
|
-
C: (f, a) => f(...a)
|
|
550
|
-
});
|
|
608
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 565, S: void 0 });
|
|
551
609
|
if (typeChanged || dataChanged || propertiesChanged) {
|
|
552
610
|
log("updating node", {
|
|
553
611
|
id,
|
|
554
612
|
type,
|
|
555
613
|
data,
|
|
556
614
|
properties
|
|
557
|
-
}, {
|
|
558
|
-
F: __dxlog_file,
|
|
559
|
-
L: 854,
|
|
560
|
-
S: void 0,
|
|
561
|
-
C: (f, a) => f(...a)
|
|
562
|
-
});
|
|
615
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 572, S: void 0 });
|
|
563
616
|
const newNode = Option.some({
|
|
564
617
|
...existing,
|
|
565
618
|
...rest,
|
|
@@ -583,12 +636,7 @@ var addNodeImpl = (graph, nodeArg) => {
|
|
|
583
636
|
type,
|
|
584
637
|
data,
|
|
585
638
|
properties
|
|
586
|
-
}, {
|
|
587
|
-
F: __dxlog_file,
|
|
588
|
-
L: 867,
|
|
589
|
-
S: void 0,
|
|
590
|
-
C: (f, a) => f(...a)
|
|
591
|
-
});
|
|
639
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 596, S: void 0 });
|
|
592
640
|
const newNode = internal._constructNode({
|
|
593
641
|
id,
|
|
594
642
|
type,
|
|
@@ -601,13 +649,23 @@ var addNodeImpl = (graph, nodeArg) => {
|
|
|
601
649
|
id,
|
|
602
650
|
node: newNode
|
|
603
651
|
});
|
|
652
|
+
const toApply = [
|
|
653
|
+
...internal._pendingExpands
|
|
654
|
+
].filter((k) => primaryParts(k)[0] === id);
|
|
655
|
+
for (const pendingKey of toApply) {
|
|
656
|
+
internal._pendingExpands.delete(pendingKey);
|
|
657
|
+
const relation2 = relationFromKey(primaryParts(pendingKey)[1]);
|
|
658
|
+
Record.set(internal._expanded, pendingKey, true);
|
|
659
|
+
internal._onExpand?.(id, relation2);
|
|
660
|
+
}
|
|
604
661
|
}
|
|
605
662
|
});
|
|
606
663
|
if (nodes) {
|
|
607
664
|
addNodesImpl(graph, nodes);
|
|
608
665
|
const _edges = nodes.map((node) => ({
|
|
609
666
|
source: id,
|
|
610
|
-
target: node.id
|
|
667
|
+
target: node.id,
|
|
668
|
+
relation: "child"
|
|
611
669
|
}));
|
|
612
670
|
addEdgesImpl(graph, _edges);
|
|
613
671
|
}
|
|
@@ -626,7 +684,7 @@ function addNode(graphOrNodeArg, nodeArg) {
|
|
|
626
684
|
}
|
|
627
685
|
}
|
|
628
686
|
var removeNodesImpl = (graph, ids, edges = false) => {
|
|
629
|
-
|
|
687
|
+
Atom.batch(() => {
|
|
630
688
|
ids.map((id) => removeNodeImpl(graph, id, edges));
|
|
631
689
|
});
|
|
632
690
|
return graph;
|
|
@@ -652,17 +710,27 @@ var removeNodeImpl = (graph, id, edges = false) => {
|
|
|
652
710
|
node: Option.none()
|
|
653
711
|
});
|
|
654
712
|
if (edges) {
|
|
655
|
-
const
|
|
656
|
-
const edgesToRemove = [
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
713
|
+
const nodeEdges = internal._registry.get(internal._edges(id));
|
|
714
|
+
const edgesToRemove = [];
|
|
715
|
+
for (const [relationKeyValue, relatedIds] of Object.entries(nodeEdges)) {
|
|
716
|
+
const relation2 = relationFromKey(relationKeyValue);
|
|
717
|
+
const isInboundRelation = relation2.direction === "inbound";
|
|
718
|
+
for (const relatedId of relatedIds) {
|
|
719
|
+
if (isInboundRelation) {
|
|
720
|
+
edgesToRemove.push({
|
|
721
|
+
source: relatedId,
|
|
722
|
+
target: id,
|
|
723
|
+
relation: inverseRelation(relation2)
|
|
724
|
+
});
|
|
725
|
+
} else {
|
|
726
|
+
edgesToRemove.push({
|
|
727
|
+
source: id,
|
|
728
|
+
target: relatedId,
|
|
729
|
+
relation: relation2
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
666
734
|
removeEdgesImpl(graph, edgesToRemove);
|
|
667
735
|
}
|
|
668
736
|
internal._onRemoveNode?.(id);
|
|
@@ -681,7 +749,7 @@ function removeNode(graphOrId, idOrEdges, edges) {
|
|
|
681
749
|
}
|
|
682
750
|
}
|
|
683
751
|
var addEdgesImpl = (graph, edges) => {
|
|
684
|
-
|
|
752
|
+
Atom.batch(() => {
|
|
685
753
|
edges.map((edge) => addEdgeImpl(graph, edge));
|
|
686
754
|
});
|
|
687
755
|
return graph;
|
|
@@ -696,45 +764,43 @@ function addEdges(graphOrEdges, edges) {
|
|
|
696
764
|
}
|
|
697
765
|
}
|
|
698
766
|
var addEdgeImpl = (graph, edgeArg) => {
|
|
767
|
+
const relation2 = normalizeRelation(edgeArg.relation);
|
|
768
|
+
const relationId = relationKey(relation2);
|
|
769
|
+
const inverse = inverseRelation(relation2);
|
|
770
|
+
const inverseId = relationKey(inverse);
|
|
699
771
|
const internal = getInternal(graph);
|
|
700
772
|
const sourceAtom = internal._edges(edgeArg.source);
|
|
701
773
|
const source = internal._registry.get(sourceAtom);
|
|
702
|
-
|
|
703
|
-
|
|
774
|
+
const sourceList = source[relationId] ?? [];
|
|
775
|
+
if (!sourceList.includes(edgeArg.target)) {
|
|
776
|
+
log("add edge", {
|
|
704
777
|
source: edgeArg.source,
|
|
705
|
-
target: edgeArg.target
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
L: 1026,
|
|
709
|
-
S: void 0,
|
|
710
|
-
C: (f, a) => f(...a)
|
|
711
|
-
});
|
|
778
|
+
target: edgeArg.target,
|
|
779
|
+
relation: relationId
|
|
780
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 758, S: void 0 });
|
|
712
781
|
internal._registry.set(sourceAtom, {
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
...
|
|
782
|
+
...source,
|
|
783
|
+
[relationId]: [
|
|
784
|
+
...sourceList,
|
|
716
785
|
edgeArg.target
|
|
717
786
|
]
|
|
718
787
|
});
|
|
719
788
|
}
|
|
720
789
|
const targetAtom = internal._edges(edgeArg.target);
|
|
721
790
|
const target = internal._registry.get(targetAtom);
|
|
722
|
-
|
|
723
|
-
|
|
791
|
+
const targetList = target[inverseId] ?? [];
|
|
792
|
+
if (!targetList.includes(edgeArg.source)) {
|
|
793
|
+
log("add inverse edge", {
|
|
724
794
|
source: edgeArg.source,
|
|
725
|
-
target: edgeArg.target
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
L: 1039,
|
|
729
|
-
S: void 0,
|
|
730
|
-
C: (f, a) => f(...a)
|
|
731
|
-
});
|
|
795
|
+
target: edgeArg.target,
|
|
796
|
+
relation: inverseId
|
|
797
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 775, S: void 0 });
|
|
732
798
|
internal._registry.set(targetAtom, {
|
|
733
|
-
|
|
734
|
-
|
|
799
|
+
...target,
|
|
800
|
+
[inverseId]: [
|
|
801
|
+
...targetList,
|
|
735
802
|
edgeArg.source
|
|
736
|
-
]
|
|
737
|
-
outbound: target.outbound
|
|
803
|
+
]
|
|
738
804
|
});
|
|
739
805
|
}
|
|
740
806
|
return graph;
|
|
@@ -749,7 +815,7 @@ function addEdge(graphOrEdgeArg, edgeArg) {
|
|
|
749
815
|
}
|
|
750
816
|
}
|
|
751
817
|
var removeEdgesImpl = (graph, edges, removeOrphans = false) => {
|
|
752
|
-
|
|
818
|
+
Atom.batch(() => {
|
|
753
819
|
edges.map((edge) => removeEdgeImpl(graph, edge, removeOrphans));
|
|
754
820
|
});
|
|
755
821
|
return graph;
|
|
@@ -767,32 +833,39 @@ function removeEdges(graphOrEdges, edgesOrRemoveOrphans, removeOrphans) {
|
|
|
767
833
|
}
|
|
768
834
|
}
|
|
769
835
|
var removeEdgeImpl = (graph, edgeArg, removeOrphans = false) => {
|
|
836
|
+
const relation2 = normalizeRelation(edgeArg.relation);
|
|
837
|
+
const relationId = relationKey(relation2);
|
|
838
|
+
const inverse = inverseRelation(relation2);
|
|
839
|
+
const inverseId = relationKey(inverse);
|
|
770
840
|
const internal = getInternal(graph);
|
|
771
841
|
const sourceAtom = internal._edges(edgeArg.source);
|
|
772
842
|
const source = internal._registry.get(sourceAtom);
|
|
773
|
-
|
|
843
|
+
const sourceList = source[relationId] ?? [];
|
|
844
|
+
if (sourceList.includes(edgeArg.target)) {
|
|
774
845
|
internal._registry.set(sourceAtom, {
|
|
775
|
-
|
|
776
|
-
|
|
846
|
+
...source,
|
|
847
|
+
[relationId]: sourceList.filter((id) => id !== edgeArg.target)
|
|
777
848
|
});
|
|
778
849
|
}
|
|
779
850
|
const targetAtom = internal._edges(edgeArg.target);
|
|
780
851
|
const target = internal._registry.get(targetAtom);
|
|
781
|
-
|
|
852
|
+
const targetList = target[inverseId] ?? [];
|
|
853
|
+
if (targetList.includes(edgeArg.source)) {
|
|
782
854
|
internal._registry.set(targetAtom, {
|
|
783
|
-
|
|
784
|
-
|
|
855
|
+
...target,
|
|
856
|
+
[inverseId]: targetList.filter((id) => id !== edgeArg.source)
|
|
785
857
|
});
|
|
786
858
|
}
|
|
787
859
|
if (removeOrphans) {
|
|
788
|
-
const
|
|
789
|
-
const
|
|
790
|
-
|
|
860
|
+
const sourceAfter = internal._registry.get(sourceAtom);
|
|
861
|
+
const targetAfter = internal._registry.get(targetAtom);
|
|
862
|
+
const isEmpty = (edges) => Object.values(edges).every((ids) => ids.length === 0);
|
|
863
|
+
if (isEmpty(sourceAfter) && edgeArg.source !== RootId) {
|
|
791
864
|
removeNodesImpl(graph, [
|
|
792
865
|
edgeArg.source
|
|
793
866
|
]);
|
|
794
867
|
}
|
|
795
|
-
if (
|
|
868
|
+
if (isEmpty(targetAfter) && edgeArg.target !== RootId) {
|
|
796
869
|
removeNodesImpl(graph, [
|
|
797
870
|
edgeArg.target
|
|
798
871
|
]);
|
|
@@ -812,35 +885,33 @@ function removeEdge(graphOrEdgeArg, edgeArgOrRemoveOrphans, removeOrphans) {
|
|
|
812
885
|
return removeEdgeImpl(graph, edgeArg, removeOrphansArg);
|
|
813
886
|
}
|
|
814
887
|
}
|
|
815
|
-
var
|
|
888
|
+
var make2 = (params) => {
|
|
816
889
|
return new GraphImpl(params);
|
|
817
890
|
};
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
import { log as log2 } from "@dxos/log";
|
|
843
|
-
import { byPosition, getDebugName, isNode, isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
891
|
+
var relationKey = (relation2) => {
|
|
892
|
+
const normalized = normalizeRelation(relation2);
|
|
893
|
+
return secondaryKey(normalized.kind, normalized.direction);
|
|
894
|
+
};
|
|
895
|
+
var relationFromKey = (encoded) => {
|
|
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}`"] });
|
|
900
|
+
return relation(kind, directionRaw);
|
|
901
|
+
};
|
|
902
|
+
var connectionKey = (id, relation2) => primaryKey(id, relationKey(relation2));
|
|
903
|
+
var relationFromConnectionKey = (key) => {
|
|
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}`"] });
|
|
906
|
+
return {
|
|
907
|
+
id,
|
|
908
|
+
relation: relationFromKey(encodedRelation)
|
|
909
|
+
};
|
|
910
|
+
};
|
|
911
|
+
var inverseRelation = (relation2) => {
|
|
912
|
+
const normalized = normalizeRelation(relation2);
|
|
913
|
+
return relation(normalized.kind, normalized.direction === "outbound" ? "inbound" : "outbound");
|
|
914
|
+
};
|
|
844
915
|
|
|
845
916
|
// src/node-matcher.ts
|
|
846
917
|
var node_matcher_exports = {};
|
|
@@ -864,19 +935,23 @@ var whenNodeType = (type) => (node) => node.type === type ? Option2.some(node) :
|
|
|
864
935
|
var whenEchoType = (type) => (node) => Obj.instanceOf(type, node.data) ? Option2.some(node.data) : Option2.none();
|
|
865
936
|
var whenEchoObject = (node) => Obj.isObject(node.data) ? Option2.some(node.data) : Option2.none();
|
|
866
937
|
var whenAll = (...matchers) => (node) => {
|
|
867
|
-
|
|
868
|
-
|
|
938
|
+
let first = Option2.none();
|
|
939
|
+
for (const candidate of matchers) {
|
|
940
|
+
const result = candidate(node);
|
|
869
941
|
if (Option2.isNone(result)) {
|
|
870
942
|
return Option2.none();
|
|
871
943
|
}
|
|
944
|
+
if (Option2.isNone(first)) {
|
|
945
|
+
first = result;
|
|
946
|
+
}
|
|
872
947
|
}
|
|
873
|
-
return
|
|
948
|
+
return first;
|
|
874
949
|
};
|
|
875
950
|
var whenAny = (...matchers) => (node) => {
|
|
876
|
-
for (const
|
|
877
|
-
const result =
|
|
951
|
+
for (const candidate of matchers) {
|
|
952
|
+
const result = candidate(node);
|
|
878
953
|
if (Option2.isSome(result)) {
|
|
879
|
-
return
|
|
954
|
+
return result;
|
|
880
955
|
}
|
|
881
956
|
}
|
|
882
957
|
return Option2.none();
|
|
@@ -886,25 +961,68 @@ var whenEchoObjectMatches = (node) => Obj.isObject(node.data) ? Option2.some(nod
|
|
|
886
961
|
var whenNot = (matcher) => (node) => Option2.isNone(matcher(node)) ? Option2.some(node) : Option2.none();
|
|
887
962
|
|
|
888
963
|
// src/graph-builder.ts
|
|
889
|
-
var
|
|
890
|
-
|
|
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";
|
|
991
|
+
var GraphBuilderTypeId = /* @__PURE__ */ Symbol.for("@dxos/app-graph/GraphBuilder");
|
|
891
992
|
var GraphBuilderImpl = class {
|
|
892
993
|
[GraphBuilderTypeId] = GraphBuilderTypeId;
|
|
893
994
|
pipe() {
|
|
894
995
|
return Pipeable2.pipeArguments(this, arguments);
|
|
895
996
|
}
|
|
896
997
|
// TODO(wittjosiah): Use Context.
|
|
998
|
+
/** Active subscriptions keyed by composite ID, cleaned up on node removal. */
|
|
897
999
|
_subscriptions = /* @__PURE__ */ new Map();
|
|
898
|
-
|
|
1000
|
+
/** Connector updates pending flush, keyed by connector key. */
|
|
1001
|
+
_dirtyConnectors = /* @__PURE__ */ new Map();
|
|
1002
|
+
/** Last-flushed node IDs per connector key, used for edge removal on update. */
|
|
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. */
|
|
1007
|
+
_connectorPreviousArgs = /* @__PURE__ */ new Map();
|
|
1008
|
+
/** Whether a dirty-flush task is already scheduled. */
|
|
1009
|
+
_flushScheduled = false;
|
|
1010
|
+
/** Resolves when the current flush completes. */
|
|
1011
|
+
_flushPromise = Promise.resolve();
|
|
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. */
|
|
899
1015
|
_initialized = {};
|
|
1016
|
+
/** Shared atom registry for reactive subscriptions. */
|
|
900
1017
|
_registry;
|
|
1018
|
+
/** Backing graph with internal accessors for node atoms and construction. */
|
|
901
1019
|
_graph;
|
|
902
1020
|
constructor({ registry, ...params } = {}) {
|
|
903
1021
|
this._registry = registry ?? Registry2.make();
|
|
904
|
-
const graph =
|
|
1022
|
+
const graph = make2({
|
|
905
1023
|
...params,
|
|
906
1024
|
registry: this._registry,
|
|
907
|
-
onExpand: (id,
|
|
1025
|
+
onExpand: (id, relation2) => this._onExpand(id, relation2),
|
|
908
1026
|
onInitialize: (id) => this._onInitialize(id),
|
|
909
1027
|
onRemoveNode: (id) => this._onRemoveNode(id)
|
|
910
1028
|
});
|
|
@@ -916,130 +1034,181 @@ var GraphBuilderImpl = class {
|
|
|
916
1034
|
get extensions() {
|
|
917
1035
|
return this._extensions;
|
|
918
1036
|
}
|
|
919
|
-
|
|
920
|
-
|
|
1037
|
+
/** Apply a set of node changes for a single connector key. */
|
|
1038
|
+
_applyConnectorUpdate(key, nodes, previous) {
|
|
1039
|
+
const { id, relation: relation2 } = relationFromConnectorKey(key);
|
|
1040
|
+
const ids = nodes.map((node) => node.id);
|
|
1041
|
+
const removed = previous.filter((pid) => !ids.includes(pid));
|
|
1042
|
+
this._connectorPrevious.set(key, ids);
|
|
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);
|
|
1049
|
+
removeEdges(this._graph, removed.map((target) => ({
|
|
1050
|
+
source: id,
|
|
1051
|
+
target,
|
|
1052
|
+
relation: relation2
|
|
1053
|
+
})), true);
|
|
1054
|
+
addNodes(this._graph, nodes);
|
|
1055
|
+
addEdges(this._graph, nodes.map((node) => ({
|
|
1056
|
+
source: id,
|
|
1057
|
+
target: node.id,
|
|
1058
|
+
relation: relation2
|
|
1059
|
+
})));
|
|
1060
|
+
if (ids.length > 0) {
|
|
1061
|
+
const sortedIds = [
|
|
1062
|
+
...nodes
|
|
1063
|
+
].sort((a, b) => byPosition(a.properties ?? {}, b.properties ?? {})).map((n) => n.id);
|
|
1064
|
+
sortEdges(this._graph, id, relation2, sortedIds);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
_scheduleDirtyFlush() {
|
|
1068
|
+
if (!this._flushScheduled) {
|
|
1069
|
+
this._flushScheduled = true;
|
|
1070
|
+
this._flushPromise = scheduleTask(() => {
|
|
1071
|
+
this._flushScheduled = false;
|
|
1072
|
+
while (this._dirtyConnectors.size > 0) {
|
|
1073
|
+
const entries = [
|
|
1074
|
+
...this._dirtyConnectors.entries()
|
|
1075
|
+
];
|
|
1076
|
+
this._dirtyConnectors.clear();
|
|
1077
|
+
Atom2.batch(() => {
|
|
1078
|
+
for (const [key, { nodes, previous }] of entries) {
|
|
1079
|
+
this._applyConnectorUpdate(key, nodes, previous);
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
}, {
|
|
1084
|
+
strategy: "smooth"
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
_resolvers = Atom2.family((id) => {
|
|
1089
|
+
return Atom2.make((get2) => {
|
|
921
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);
|
|
922
1091
|
});
|
|
923
1092
|
});
|
|
924
|
-
_connectors =
|
|
925
|
-
return
|
|
926
|
-
const
|
|
1093
|
+
_connectors = Atom2.family((key) => {
|
|
1094
|
+
return Atom2.make((get2) => {
|
|
1095
|
+
const { id, relation: relation2 } = relationFromConnectorKey(key);
|
|
927
1096
|
const node = this._graph.node(id);
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1097
|
+
const sourceNode = Option3.getOrElse(get2(node), () => void 0);
|
|
1098
|
+
if (!sourceNode) {
|
|
1099
|
+
return [];
|
|
1100
|
+
}
|
|
1101
|
+
const extensions = Function2.pipe(get2(this._extensions), Record2.values, Array2.sortBy(byPosition), Array2.filter((ext) => relationKey(ext.relation ?? "child") === relationKey(relation2) && ext.connector != null));
|
|
1102
|
+
const nodes = [];
|
|
1103
|
+
for (const ext of extensions) {
|
|
1104
|
+
const result = get2(ext.connector(node));
|
|
1105
|
+
nodes.push(...result);
|
|
1106
|
+
}
|
|
1107
|
+
return nodes;
|
|
1108
|
+
}).pipe(Atom2.withLabel(`graph-builder:connectors:${key}`));
|
|
939
1109
|
});
|
|
940
|
-
_onExpand(id,
|
|
1110
|
+
_onExpand(id, relation2) {
|
|
941
1111
|
log2("onExpand", {
|
|
942
1112
|
id,
|
|
943
|
-
relation,
|
|
1113
|
+
relation: relation2,
|
|
944
1114
|
registry: getDebugName(this._registry)
|
|
945
|
-
}, {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
const
|
|
1115
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 136, S: this });
|
|
1116
|
+
this._expandRelation(id, relation2);
|
|
1117
|
+
if (relation2.kind === "child" && relation2.direction === "outbound") {
|
|
1118
|
+
expand(this._graph, id, "action");
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
_expandRelation(id, relation2) {
|
|
1122
|
+
const key = connectorKey(id, relation2);
|
|
1123
|
+
const connectors = this._connectors(key);
|
|
1124
|
+
const cancel = this._registry.subscribe(connectors, (rawNodes) => {
|
|
1125
|
+
const nodes = qualifyNodeArgs(id)(rawNodes);
|
|
1126
|
+
const previous = this._connectorPrevious.get(key) ?? [];
|
|
954
1127
|
const ids = nodes.map((n) => n.id);
|
|
955
|
-
|
|
956
|
-
|
|
1128
|
+
if (ids.length === previous.length && ids.every((nodeId, idx) => nodeId === previous[idx])) {
|
|
1129
|
+
const prevArgs = this._connectorPreviousArgs.get(key);
|
|
1130
|
+
if (prevArgs && nodeArgsUnchanged(prevArgs, nodes)) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
957
1134
|
log2("update", {
|
|
958
1135
|
id,
|
|
959
|
-
relation,
|
|
960
|
-
ids
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
S: this,
|
|
966
|
-
C: (f, a) => f(...a)
|
|
1136
|
+
relation: relation2,
|
|
1137
|
+
ids
|
|
1138
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 160, S: this });
|
|
1139
|
+
this._dirtyConnectors.set(key, {
|
|
1140
|
+
nodes,
|
|
1141
|
+
previous
|
|
967
1142
|
});
|
|
968
|
-
|
|
969
|
-
Atom3.batch(() => {
|
|
970
|
-
removeEdges(this._graph, removed.map((target) => ({
|
|
971
|
-
source: id,
|
|
972
|
-
target
|
|
973
|
-
})), true);
|
|
974
|
-
addNodes(this._graph, nodes);
|
|
975
|
-
addEdges(this._graph, nodes.map((node) => relation === "outbound" ? {
|
|
976
|
-
source: id,
|
|
977
|
-
target: node.id
|
|
978
|
-
} : {
|
|
979
|
-
source: node.id,
|
|
980
|
-
target: id
|
|
981
|
-
}));
|
|
982
|
-
sortEdges(this._graph, id, relation, nodes.map(({ id: id2 }) => id2));
|
|
983
|
-
});
|
|
984
|
-
};
|
|
985
|
-
if (typeof requestAnimationFrame === "function") {
|
|
986
|
-
requestAnimationFrame(update);
|
|
987
|
-
} else {
|
|
988
|
-
update();
|
|
989
|
-
}
|
|
1143
|
+
this._scheduleDirtyFlush();
|
|
990
1144
|
}, {
|
|
991
1145
|
immediate: true
|
|
992
1146
|
});
|
|
993
|
-
this._subscriptions.set(id, cancel);
|
|
1147
|
+
this._subscriptions.set(subscriptionKey(id, "expand", key), cancel);
|
|
994
1148
|
}
|
|
995
|
-
// TODO(wittjosiah): If the same node is added by a connector, the resolver should probably cancel itself?
|
|
996
1149
|
async _onInitialize(id) {
|
|
997
1150
|
log2("onInitialize", {
|
|
998
1151
|
id
|
|
999
|
-
}, {
|
|
1000
|
-
F: __dxlog_file2,
|
|
1001
|
-
L: 227,
|
|
1002
|
-
S: this,
|
|
1003
|
-
C: (f, a) => f(...a)
|
|
1004
|
-
});
|
|
1152
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 176, S: this });
|
|
1005
1153
|
const resolver = this._resolvers(id);
|
|
1006
1154
|
const cancel = this._registry.subscribe(resolver, (node) => {
|
|
1007
1155
|
const trigger = this._initialized[id];
|
|
1156
|
+
const connectorOwned = [
|
|
1157
|
+
...this._connectorPrevious.values()
|
|
1158
|
+
].some((ids) => ids.includes(id));
|
|
1008
1159
|
Option3.match(node, {
|
|
1009
1160
|
onSome: (node2) => {
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
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
|
+
}
|
|
1013
1176
|
trigger?.wake();
|
|
1014
1177
|
},
|
|
1015
1178
|
onNone: () => {
|
|
1016
1179
|
trigger?.wake();
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1180
|
+
if (!connectorOwned) {
|
|
1181
|
+
removeNodes(this._graph, [
|
|
1182
|
+
id
|
|
1183
|
+
]);
|
|
1184
|
+
}
|
|
1020
1185
|
}
|
|
1021
1186
|
});
|
|
1022
1187
|
}, {
|
|
1023
1188
|
immediate: true
|
|
1024
1189
|
});
|
|
1025
|
-
this._subscriptions.set(id, cancel);
|
|
1190
|
+
this._subscriptions.set(subscriptionKey(id, "init"), cancel);
|
|
1026
1191
|
}
|
|
1027
1192
|
_onRemoveNode(id) {
|
|
1028
|
-
this._subscriptions
|
|
1029
|
-
|
|
1193
|
+
for (const [key, cleanup] of this._subscriptions) {
|
|
1194
|
+
if (primaryParts(key)[0] === id) {
|
|
1195
|
+
cleanup();
|
|
1196
|
+
this._subscriptions.delete(key);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1030
1199
|
}
|
|
1031
1200
|
};
|
|
1032
|
-
var
|
|
1201
|
+
var make3 = (params) => {
|
|
1033
1202
|
return new GraphBuilderImpl(params);
|
|
1034
1203
|
};
|
|
1035
1204
|
var from = (pickle, registry) => {
|
|
1036
1205
|
if (!pickle) {
|
|
1037
|
-
return
|
|
1206
|
+
return make3({
|
|
1038
1207
|
registry
|
|
1039
1208
|
});
|
|
1040
1209
|
}
|
|
1041
1210
|
const { nodes, edges } = JSON.parse(pickle);
|
|
1042
|
-
return
|
|
1211
|
+
return make3({
|
|
1043
1212
|
nodes,
|
|
1044
1213
|
edges,
|
|
1045
1214
|
registry
|
|
@@ -1079,14 +1248,11 @@ function removeExtension(builderOrId, id) {
|
|
|
1079
1248
|
}
|
|
1080
1249
|
var exploreImpl = async (builder, options, path = []) => {
|
|
1081
1250
|
const internal = builder;
|
|
1082
|
-
const { registry = Registry2.make(), source = RootId, relation
|
|
1251
|
+
const { registry = Registry2.make(), source = RootId, relation: relation2, visitor } = options;
|
|
1083
1252
|
if (path.includes(source)) {
|
|
1084
1253
|
return;
|
|
1085
1254
|
}
|
|
1086
|
-
|
|
1087
|
-
const { yieldOrContinue } = await import("main-thread-scheduling");
|
|
1088
|
-
await yieldOrContinue("idle");
|
|
1089
|
-
}
|
|
1255
|
+
await yieldOrContinue("idle");
|
|
1090
1256
|
const node = registry.get(internal._graph.nodeOrThrow(source));
|
|
1091
1257
|
const shouldContinue = await visitor(node, [
|
|
1092
1258
|
...path,
|
|
@@ -1095,13 +1261,13 @@ var exploreImpl = async (builder, options, path = []) => {
|
|
|
1095
1261
|
if (shouldContinue === false) {
|
|
1096
1262
|
return;
|
|
1097
1263
|
}
|
|
1098
|
-
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));
|
|
1099
1265
|
await Promise.all(nodes.map((nodeArg) => {
|
|
1100
1266
|
registry.set(internal._graph._node(nodeArg.id), internal._graph._constructNode(nodeArg));
|
|
1101
1267
|
return exploreImpl(builder, {
|
|
1102
1268
|
registry,
|
|
1103
1269
|
source: nodeArg.id,
|
|
1104
|
-
relation,
|
|
1270
|
+
relation: relation2,
|
|
1105
1271
|
visitor
|
|
1106
1272
|
}, [
|
|
1107
1273
|
...path,
|
|
@@ -1137,13 +1303,17 @@ function destroy(builder) {
|
|
|
1137
1303
|
return destroyImpl(builder);
|
|
1138
1304
|
}
|
|
1139
1305
|
}
|
|
1306
|
+
var flush = (builder) => {
|
|
1307
|
+
return builder._flushPromise;
|
|
1308
|
+
};
|
|
1140
1309
|
var createExtensionRaw = (extension) => {
|
|
1141
|
-
const { id, position
|
|
1310
|
+
const { id, position, relation: relation2 = "child", resolver: _resolver, connector: _connector, actions: _actions, actionGroups: _actionGroups } = extension;
|
|
1311
|
+
const normalizedRelation = normalizeRelation(relation2);
|
|
1142
1312
|
const getId = (key) => `${id}/${key}`;
|
|
1143
|
-
const resolver = _resolver &&
|
|
1144
|
-
const connector = _connector &&
|
|
1145
|
-
const actionGroups = _actionGroups &&
|
|
1146
|
-
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}`)));
|
|
1147
1317
|
return [
|
|
1148
1318
|
resolver ? {
|
|
1149
1319
|
id: getId("resolver"),
|
|
@@ -1153,8 +1323,8 @@ var createExtensionRaw = (extension) => {
|
|
|
1153
1323
|
connector ? {
|
|
1154
1324
|
id: getId("connector"),
|
|
1155
1325
|
position,
|
|
1156
|
-
relation,
|
|
1157
|
-
connector:
|
|
1326
|
+
relation: normalizedRelation,
|
|
1327
|
+
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
1158
1328
|
try {
|
|
1159
1329
|
return get2(connector(node));
|
|
1160
1330
|
} catch (error) {
|
|
@@ -1162,21 +1332,16 @@ var createExtensionRaw = (extension) => {
|
|
|
1162
1332
|
id: getId("connector"),
|
|
1163
1333
|
node,
|
|
1164
1334
|
error
|
|
1165
|
-
}, {
|
|
1166
|
-
F: __dxlog_file2,
|
|
1167
|
-
L: 509,
|
|
1168
|
-
S: void 0,
|
|
1169
|
-
C: (f, a) => f(...a)
|
|
1170
|
-
});
|
|
1335
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 383, S: void 0 });
|
|
1171
1336
|
return [];
|
|
1172
1337
|
}
|
|
1173
|
-
}).pipe(
|
|
1338
|
+
}).pipe(Atom2.withLabel(`graph-builder:connector:${id}`)))
|
|
1174
1339
|
} : void 0,
|
|
1175
1340
|
actionGroups ? {
|
|
1176
1341
|
id: getId("actionGroups"),
|
|
1177
1342
|
position,
|
|
1178
|
-
relation:
|
|
1179
|
-
connector:
|
|
1343
|
+
relation: actionRelation(),
|
|
1344
|
+
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
1180
1345
|
try {
|
|
1181
1346
|
return get2(actionGroups(node)).map((arg) => ({
|
|
1182
1347
|
...arg,
|
|
@@ -1188,21 +1353,16 @@ var createExtensionRaw = (extension) => {
|
|
|
1188
1353
|
id: getId("actionGroups"),
|
|
1189
1354
|
node,
|
|
1190
1355
|
error
|
|
1191
|
-
}, {
|
|
1192
|
-
F: __dxlog_file2,
|
|
1193
|
-
L: 530,
|
|
1194
|
-
S: void 0,
|
|
1195
|
-
C: (f, a) => f(...a)
|
|
1196
|
-
});
|
|
1356
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 404, S: void 0 });
|
|
1197
1357
|
return [];
|
|
1198
1358
|
}
|
|
1199
|
-
}).pipe(
|
|
1359
|
+
}).pipe(Atom2.withLabel(`graph-builder:connector:actionGroups:${id}`)))
|
|
1200
1360
|
} : void 0,
|
|
1201
1361
|
actions ? {
|
|
1202
1362
|
id: getId("actions"),
|
|
1203
1363
|
position,
|
|
1204
|
-
relation:
|
|
1205
|
-
connector:
|
|
1364
|
+
relation: actionRelation(),
|
|
1365
|
+
connector: Atom2.family((node) => Atom2.make((get2) => {
|
|
1206
1366
|
try {
|
|
1207
1367
|
return get2(actions(node)).map((arg) => ({
|
|
1208
1368
|
...arg,
|
|
@@ -1213,15 +1373,10 @@ var createExtensionRaw = (extension) => {
|
|
|
1213
1373
|
id: getId("actions"),
|
|
1214
1374
|
node,
|
|
1215
1375
|
error
|
|
1216
|
-
}, {
|
|
1217
|
-
F: __dxlog_file2,
|
|
1218
|
-
L: 547,
|
|
1219
|
-
S: void 0,
|
|
1220
|
-
C: (f, a) => f(...a)
|
|
1221
|
-
});
|
|
1376
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 424, S: void 0 });
|
|
1222
1377
|
return [];
|
|
1223
1378
|
}
|
|
1224
|
-
}).pipe(
|
|
1379
|
+
}).pipe(Atom2.withLabel(`graph-builder:connector:actions:${id}`)))
|
|
1225
1380
|
} : void 0
|
|
1226
1381
|
].filter(isNonNullable2);
|
|
1227
1382
|
};
|
|
@@ -1230,27 +1385,22 @@ var runEffectSyncWithFallback = (effect, context2, extensionId, fallback) => {
|
|
|
1230
1385
|
log2.warn("Extension failed", {
|
|
1231
1386
|
extension: extensionId,
|
|
1232
1387
|
error
|
|
1233
|
-
}, {
|
|
1234
|
-
F: __dxlog_file2,
|
|
1235
|
-
L: 590,
|
|
1236
|
-
S: void 0,
|
|
1237
|
-
C: (f, a) => f(...a)
|
|
1238
|
-
});
|
|
1388
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 441, S: void 0 });
|
|
1239
1389
|
return Effect.succeed(fallback);
|
|
1240
1390
|
})));
|
|
1241
1391
|
};
|
|
1242
1392
|
var createExtension = (options) => Effect.map(Effect.context(), (context2) => {
|
|
1243
|
-
const { id, match: match3, actions, connector, resolver, relation, position } = options;
|
|
1393
|
+
const { id, match: match3, actions, connector, resolver, relation: relation2, position } = options;
|
|
1244
1394
|
const connectorExtension = connector ? createConnectorWithRuntime(id, match3, connector, context2) : void 0;
|
|
1245
|
-
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) => ({
|
|
1246
1396
|
...action,
|
|
1247
1397
|
// Attach captured context for action execution.
|
|
1248
1398
|
_actionContext: context2
|
|
1249
1399
|
}))), Option3.getOrElse(() => []))) : void 0;
|
|
1250
|
-
const resolverExtension = resolver ? (nodeId) =>
|
|
1400
|
+
const resolverExtension = resolver ? (nodeId) => Atom2.make((get2) => runEffectSyncWithFallback(resolver(nodeId, get2), context2, id, null) ?? null) : void 0;
|
|
1251
1401
|
return createExtensionRaw({
|
|
1252
1402
|
id,
|
|
1253
|
-
relation,
|
|
1403
|
+
relation: relation2,
|
|
1254
1404
|
position,
|
|
1255
1405
|
connector: connectorExtension,
|
|
1256
1406
|
actions: actionsExtension,
|
|
@@ -1258,22 +1408,44 @@ var createExtension = (options) => Effect.map(Effect.context(), (context2) => {
|
|
|
1258
1408
|
});
|
|
1259
1409
|
});
|
|
1260
1410
|
var createConnector = (matcher, factory) => {
|
|
1261
|
-
return (node) =>
|
|
1411
|
+
return (node) => Atom2.make((get2) => Function2.pipe(get2(node), Option3.flatMap(matcher), Option3.map((data) => factory(data, get2)), Option3.getOrElse(() => [])));
|
|
1262
1412
|
};
|
|
1263
1413
|
var createConnectorWithRuntime = (extensionId, matcher, factory, context2) => {
|
|
1264
|
-
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(() => [])));
|
|
1265
1415
|
};
|
|
1266
1416
|
var createTypeExtension = (options) => {
|
|
1267
|
-
const { id, type, actions, connector, relation, position } = options;
|
|
1417
|
+
const { id, type, actions, connector, relation: relation2, position } = options;
|
|
1268
1418
|
return createExtension({
|
|
1269
1419
|
id,
|
|
1270
1420
|
match: whenEchoType(type),
|
|
1271
1421
|
actions,
|
|
1272
1422
|
connector,
|
|
1273
|
-
relation,
|
|
1423
|
+
relation: relation2,
|
|
1274
1424
|
position
|
|
1275
1425
|
});
|
|
1276
1426
|
};
|
|
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));
|
|
1441
|
+
var relationFromConnectorKey = (key) => {
|
|
1442
|
+
const [id, encodedRelation] = primaryParts(key);
|
|
1443
|
+
return {
|
|
1444
|
+
id,
|
|
1445
|
+
relation: relationFromKey(encodedRelation)
|
|
1446
|
+
};
|
|
1447
|
+
};
|
|
1448
|
+
var subscriptionKey = (id, kind, detail) => detail != null ? primaryKey(id, kind, detail) : primaryKey(id, kind);
|
|
1277
1449
|
var flattenExtensions = (extension, acc = []) => {
|
|
1278
1450
|
if (Array2.isArray(extension)) {
|
|
1279
1451
|
return [
|
|
@@ -1287,11 +1459,19 @@ var flattenExtensions = (extension, acc = []) => {
|
|
|
1287
1459
|
];
|
|
1288
1460
|
}
|
|
1289
1461
|
};
|
|
1462
|
+
|
|
1290
1463
|
export {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
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
|
|
1296
1476
|
};
|
|
1297
|
-
//# sourceMappingURL=
|
|
1477
|
+
//# sourceMappingURL=chunk-32XXJE6M.mjs.map
|