@workglow/util 0.0.121 → 0.0.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +232 -2098
- package/dist/browser.js.map +6 -25
- package/dist/bun.js +236 -2099
- package/dist/bun.js.map +6 -25
- package/dist/common.d.ts +0 -15
- package/dist/common.d.ts.map +1 -1
- package/dist/compress-browser.d.ts +7 -0
- package/dist/compress-browser.d.ts.map +1 -0
- package/dist/compress-browser.js +18 -0
- package/dist/compress-browser.js.map +10 -0
- package/dist/compress-node.d.ts +7 -0
- package/dist/compress-node.d.ts.map +1 -0
- package/dist/compress-node.js +25 -0
- package/dist/compress-node.js.map +10 -0
- package/dist/credentials/ChainedCredentialStore.d.ts.map +1 -1
- package/dist/credentials/EnvCredentialStore.d.ts.map +1 -1
- package/dist/credentials/InMemoryCredentialStore.d.ts.map +1 -1
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/ServiceRegistry.d.ts.map +1 -1
- package/dist/events/EventEmitter.d.ts.map +1 -1
- package/dist/graph/directedAcyclicGraph.d.ts.map +1 -1
- package/dist/graph/directedGraph.d.ts.map +1 -1
- package/dist/graph/errors.d.ts.map +1 -1
- package/dist/graph/graph.d.ts.map +1 -1
- package/dist/graph-entry.d.ts +7 -0
- package/dist/graph-entry.d.ts.map +1 -0
- package/dist/graph-entry.js +539 -0
- package/dist/graph-entry.js.map +15 -0
- package/dist/logging/ConsoleLogger.d.ts.map +1 -1
- package/dist/logging/NullLogger.d.ts.map +1 -1
- package/dist/media-browser.d.ts +8 -0
- package/dist/media-browser.d.ts.map +1 -0
- package/dist/media-browser.js +73 -0
- package/dist/media-browser.js.map +11 -0
- package/dist/media-node.d.ts +8 -0
- package/dist/media-node.d.ts.map +1 -0
- package/dist/media-node.js +50 -0
- package/dist/media-node.js.map +11 -0
- package/dist/node.js +246 -2108
- package/dist/node.js.map +6 -25
- package/dist/schema-entry.d.ts +17 -0
- package/dist/schema-entry.d.ts.map +1 -0
- package/dist/schema-entry.js +774 -0
- package/dist/schema-entry.js.map +18 -0
- package/dist/telemetry/ConsoleTelemetryProvider.d.ts.map +1 -1
- package/dist/telemetry/NoopTelemetryProvider.d.ts.map +1 -1
- package/dist/telemetry/OTelTelemetryProvider.d.ts.map +1 -1
- package/dist/types.d.ts +0 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities/BaseError.d.ts.map +1 -1
- package/dist/vector/Tensor.d.ts +1 -1
- package/dist/vector/Tensor.d.ts.map +1 -1
- package/dist/vector/TypedArray.d.ts +4 -4
- package/dist/vector/TypedArray.d.ts.map +1 -1
- package/dist/worker/Worker.browser.d.ts +6 -1
- package/dist/worker/Worker.browser.d.ts.map +1 -1
- package/dist/worker/Worker.bun.d.ts +6 -1
- package/dist/worker/Worker.bun.d.ts.map +1 -1
- package/dist/worker/Worker.node.d.ts +6 -1
- package/dist/worker/Worker.node.d.ts.map +1 -1
- package/dist/worker/WorkerManager.d.ts +7 -1
- package/dist/worker/WorkerManager.d.ts.map +1 -1
- package/dist/worker/{WorkerServer.d.ts → WorkerServerBase.d.ts} +5 -4
- package/dist/worker/WorkerServerBase.d.ts.map +1 -0
- package/dist/worker-browser.js +894 -0
- package/dist/worker-browser.js.map +19 -0
- package/dist/worker-bun.js +895 -0
- package/dist/worker-bun.js.map +19 -0
- package/dist/worker-entry.d.ts +25 -0
- package/dist/worker-entry.d.ts.map +1 -0
- package/dist/worker-node.js +914 -0
- package/dist/worker-node.js.map +19 -0
- package/package.json +59 -19
- package/dist/mcp/McpAuthProvider.d.ts +0 -70
- package/dist/mcp/McpAuthProvider.d.ts.map +0 -1
- package/dist/mcp/McpAuthTypes.d.ts +0 -218
- package/dist/mcp/McpAuthTypes.d.ts.map +0 -1
- package/dist/mcp/McpClientUtil.browser.d.ts +0 -198
- package/dist/mcp/McpClientUtil.browser.d.ts.map +0 -1
- package/dist/mcp/McpClientUtil.node.d.ts +0 -222
- package/dist/mcp/McpClientUtil.node.d.ts.map +0 -1
- package/dist/worker/WorkerServer.d.ts.map +0 -1
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
// src/utilities/BaseError.ts
|
|
2
|
+
class BaseError {
|
|
3
|
+
static type = "BaseError";
|
|
4
|
+
message;
|
|
5
|
+
name;
|
|
6
|
+
stack;
|
|
7
|
+
constructor(message = "") {
|
|
8
|
+
this.message = message;
|
|
9
|
+
const constructor = this.constructor;
|
|
10
|
+
this.name = constructor.type ?? this.constructor.name;
|
|
11
|
+
if (typeof Error !== "undefined" && Error.captureStackTrace) {
|
|
12
|
+
const temp = { stack: "" };
|
|
13
|
+
Error.captureStackTrace(temp, this.constructor);
|
|
14
|
+
this.stack = temp.stack;
|
|
15
|
+
} else {
|
|
16
|
+
try {
|
|
17
|
+
throw new Error(message);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
if (err instanceof Error) {
|
|
20
|
+
this.stack = err.stack;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
toString() {
|
|
26
|
+
return `${this.name}: ${this.message}`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/graph/errors.ts
|
|
31
|
+
class NodeAlreadyExistsError extends BaseError {
|
|
32
|
+
static type = "NodeAlreadyExistsError";
|
|
33
|
+
newNode;
|
|
34
|
+
oldNode;
|
|
35
|
+
identity;
|
|
36
|
+
constructor(newNode, oldNode, identity) {
|
|
37
|
+
super(`${JSON.stringify(newNode)} shares an identity (${String(identity)}) with ${JSON.stringify(oldNode)}`);
|
|
38
|
+
this.newNode = newNode;
|
|
39
|
+
this.oldNode = oldNode;
|
|
40
|
+
this.identity = identity;
|
|
41
|
+
this.name = "NodeAlreadyExistsError";
|
|
42
|
+
Object.setPrototypeOf(this, NodeAlreadyExistsError.prototype);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class NodeDoesntExistError extends BaseError {
|
|
47
|
+
static type = "NodeDoesntExistError";
|
|
48
|
+
identity;
|
|
49
|
+
constructor(identity) {
|
|
50
|
+
super(`A node with identity ${String(identity)} doesn't exist in the graph`);
|
|
51
|
+
this.identity = identity;
|
|
52
|
+
this.name = "NodeDoesntExistError";
|
|
53
|
+
Object.setPrototypeOf(this, NodeDoesntExistError.prototype);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class CycleError extends BaseError {
|
|
58
|
+
static type = "CycleError";
|
|
59
|
+
constructor(message) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = "CycleError";
|
|
62
|
+
Object.setPrototypeOf(this, CycleError.prototype);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/events/EventEmitter.ts
|
|
67
|
+
class EventEmitter {
|
|
68
|
+
listeners = {};
|
|
69
|
+
removeAllListeners(event) {
|
|
70
|
+
if (event) {
|
|
71
|
+
delete this.listeners[event];
|
|
72
|
+
} else {
|
|
73
|
+
this.listeners = {};
|
|
74
|
+
}
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
on(event, listener) {
|
|
78
|
+
const listeners = this.listeners[event] || (this.listeners[event] = []);
|
|
79
|
+
listeners.push({ listener });
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
off(event, listener) {
|
|
83
|
+
const listeners = this.listeners[event];
|
|
84
|
+
if (!listeners)
|
|
85
|
+
return this;
|
|
86
|
+
const index = listeners.findIndex((l) => l.listener === listener);
|
|
87
|
+
if (index >= 0) {
|
|
88
|
+
listeners.splice(index, 1);
|
|
89
|
+
}
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
once(event, listener) {
|
|
93
|
+
const listeners = this.listeners[event] || (this.listeners[event] = []);
|
|
94
|
+
listeners.push({ listener, once: true });
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
waitOn(event) {
|
|
98
|
+
return new Promise((resolve) => {
|
|
99
|
+
const listener = (...args) => {
|
|
100
|
+
resolve(args);
|
|
101
|
+
};
|
|
102
|
+
this.once(event, listener);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
emit(event, ...args) {
|
|
106
|
+
const listeners = this.listeners[event];
|
|
107
|
+
if (listeners) {
|
|
108
|
+
listeners.forEach(({ listener }) => {
|
|
109
|
+
listener(...args);
|
|
110
|
+
});
|
|
111
|
+
this.listeners[event] = listeners.filter((l) => !l.once);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
subscribe(event, listener) {
|
|
115
|
+
this.on(event, listener);
|
|
116
|
+
return () => this.off(event, listener);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/graph/graph.ts
|
|
121
|
+
class Graph {
|
|
122
|
+
nodes;
|
|
123
|
+
adjacency;
|
|
124
|
+
nodeIdentity;
|
|
125
|
+
edgeIdentity;
|
|
126
|
+
constructor(nodeIdentity, edgeIdentity) {
|
|
127
|
+
this.nodes = new Map;
|
|
128
|
+
this.adjacency = [];
|
|
129
|
+
this.nodeIdentity = nodeIdentity;
|
|
130
|
+
this.edgeIdentity = edgeIdentity;
|
|
131
|
+
}
|
|
132
|
+
events = new EventEmitter;
|
|
133
|
+
on(name, fn) {
|
|
134
|
+
this.events.on.call(this.events, name, fn);
|
|
135
|
+
}
|
|
136
|
+
off(name, fn) {
|
|
137
|
+
this.events.off.call(this.events, name, fn);
|
|
138
|
+
}
|
|
139
|
+
emit(name, ...args) {
|
|
140
|
+
this.events.emit(name, ...args);
|
|
141
|
+
}
|
|
142
|
+
insert(node) {
|
|
143
|
+
const id = this.nodeIdentity(node);
|
|
144
|
+
const isOverwrite = this.nodes.has(id);
|
|
145
|
+
if (isOverwrite) {
|
|
146
|
+
throw new NodeAlreadyExistsError(node, this.nodes.get(id), id);
|
|
147
|
+
}
|
|
148
|
+
this.nodes.set(id, node);
|
|
149
|
+
this.adjacency.map((adj) => adj.push(null));
|
|
150
|
+
this.adjacency.push(new Array(this.adjacency.length + 1).fill(null));
|
|
151
|
+
this.emit("node-added", id);
|
|
152
|
+
return id;
|
|
153
|
+
}
|
|
154
|
+
replace(node) {
|
|
155
|
+
const id = this.nodeIdentity(node);
|
|
156
|
+
const isOverwrite = this.nodes.has(id);
|
|
157
|
+
if (!isOverwrite) {
|
|
158
|
+
throw new NodeDoesntExistError(id);
|
|
159
|
+
}
|
|
160
|
+
this.nodes.set(id, node);
|
|
161
|
+
this.emit("node-replaced", id);
|
|
162
|
+
}
|
|
163
|
+
upsert(node) {
|
|
164
|
+
const id = this.nodeIdentity(node);
|
|
165
|
+
const isOverwrite = this.nodes.has(id);
|
|
166
|
+
this.nodes.set(id, node);
|
|
167
|
+
if (!isOverwrite) {
|
|
168
|
+
this.adjacency.map((adj) => adj.push(null));
|
|
169
|
+
this.adjacency.push(new Array(this.adjacency.length + 1).fill(null));
|
|
170
|
+
this.emit("node-added", id);
|
|
171
|
+
} else {
|
|
172
|
+
this.emit("node-replaced", id);
|
|
173
|
+
}
|
|
174
|
+
return id;
|
|
175
|
+
}
|
|
176
|
+
addEdge(node1Identity, node2Identity, edge) {
|
|
177
|
+
if (edge === undefined) {
|
|
178
|
+
edge = true;
|
|
179
|
+
}
|
|
180
|
+
const node1Exists = this.nodes.has(node1Identity);
|
|
181
|
+
const node2Exists = this.nodes.has(node2Identity);
|
|
182
|
+
if (!node1Exists) {
|
|
183
|
+
throw new NodeDoesntExistError(node1Identity);
|
|
184
|
+
}
|
|
185
|
+
if (!node2Exists) {
|
|
186
|
+
throw new NodeDoesntExistError(node2Identity);
|
|
187
|
+
}
|
|
188
|
+
const node1Index = Array.from(this.nodes.keys()).indexOf(node1Identity);
|
|
189
|
+
const node2Index = Array.from(this.nodes.keys()).indexOf(node2Identity);
|
|
190
|
+
if (this.adjacency[node1Index][node2Index] === null) {
|
|
191
|
+
this.adjacency[node1Index][node2Index] = [edge];
|
|
192
|
+
} else {
|
|
193
|
+
if (!this.adjacency[node1Index][node2Index].includes(edge)) {
|
|
194
|
+
this.adjacency[node1Index][node2Index].push(edge);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const id = this.edgeIdentity(edge, node1Identity, node2Identity);
|
|
198
|
+
this.emit("edge-added", id);
|
|
199
|
+
return id;
|
|
200
|
+
}
|
|
201
|
+
getNodes(compareFunc) {
|
|
202
|
+
const temp = Array.from(this.nodes.values());
|
|
203
|
+
if (compareFunc !== undefined) {
|
|
204
|
+
return temp.sort(compareFunc);
|
|
205
|
+
}
|
|
206
|
+
return temp;
|
|
207
|
+
}
|
|
208
|
+
getNode(nodeIdentity) {
|
|
209
|
+
return this.nodes.get(nodeIdentity);
|
|
210
|
+
}
|
|
211
|
+
hasNode(nodeIdentity) {
|
|
212
|
+
return this.nodes.has(nodeIdentity);
|
|
213
|
+
}
|
|
214
|
+
getEdges() {
|
|
215
|
+
const toReturn = [];
|
|
216
|
+
const nodeKeys = Array.from(this.nodes.keys());
|
|
217
|
+
this.adjacency.forEach((row, rowIndex) => {
|
|
218
|
+
const node1Identity = nodeKeys[rowIndex];
|
|
219
|
+
if (node1Identity != null) {
|
|
220
|
+
row.forEach((edges, colIndex) => {
|
|
221
|
+
if (edges !== null) {
|
|
222
|
+
const node2Identity = nodeKeys[colIndex];
|
|
223
|
+
if (node2Identity != null) {
|
|
224
|
+
for (const edge of edges) {
|
|
225
|
+
toReturn.push([node1Identity, node2Identity, edge]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
return toReturn;
|
|
233
|
+
}
|
|
234
|
+
outEdges(node1Identity) {
|
|
235
|
+
const nodeKeys = Array.from(this.nodes.keys());
|
|
236
|
+
const nodeIndex = nodeKeys.indexOf(node1Identity);
|
|
237
|
+
const toReturn = [];
|
|
238
|
+
this.adjacency[nodeIndex].forEach((edges, colIndex) => {
|
|
239
|
+
if (edges !== null) {
|
|
240
|
+
const node2Identity = nodeKeys[colIndex];
|
|
241
|
+
if (node2Identity != null) {
|
|
242
|
+
for (const edge of edges) {
|
|
243
|
+
toReturn.push([node1Identity, node2Identity, edge]);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return toReturn;
|
|
249
|
+
}
|
|
250
|
+
inEdges(node2Identity) {
|
|
251
|
+
const nodeKeys = Array.from(this.nodes.keys());
|
|
252
|
+
const node2Index = nodeKeys.indexOf(node2Identity);
|
|
253
|
+
const toReturn = [];
|
|
254
|
+
this.adjacency.forEach((row, rowIndex) => {
|
|
255
|
+
const node1Identity = nodeKeys[rowIndex];
|
|
256
|
+
const edges = row[node2Index];
|
|
257
|
+
if (edges !== null) {
|
|
258
|
+
for (const edge of edges) {
|
|
259
|
+
toReturn.push([node1Identity, node2Identity, edge]);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
return toReturn;
|
|
264
|
+
}
|
|
265
|
+
nodeEdges(nodeIdentity) {
|
|
266
|
+
return [...this.outEdges(nodeIdentity), ...this.inEdges(nodeIdentity)];
|
|
267
|
+
}
|
|
268
|
+
removeEdge(node1Identity, node2Identity, edgeIdentity) {
|
|
269
|
+
const node1Exists = this.nodes.has(node1Identity);
|
|
270
|
+
const node2Exists = this.nodes.has(node2Identity);
|
|
271
|
+
if (!node1Exists) {
|
|
272
|
+
throw new NodeDoesntExistError(node1Identity);
|
|
273
|
+
}
|
|
274
|
+
if (!node2Exists) {
|
|
275
|
+
throw new NodeDoesntExistError(node2Identity);
|
|
276
|
+
}
|
|
277
|
+
const node1Index = Array.from(this.nodes.keys()).indexOf(node1Identity);
|
|
278
|
+
const node2Index = Array.from(this.nodes.keys()).indexOf(node2Identity);
|
|
279
|
+
if (edgeIdentity === undefined) {
|
|
280
|
+
this.adjacency[node1Index][node2Index] = null;
|
|
281
|
+
} else {
|
|
282
|
+
for (const row of this.adjacency) {
|
|
283
|
+
for (const edgelist of row) {
|
|
284
|
+
if (edgelist !== null) {
|
|
285
|
+
for (let edgeIndex = 0;edgeIndex < edgelist.length; edgeIndex++) {
|
|
286
|
+
if (this.edgeIdentity(edgelist[edgeIndex], node1Identity, node2Identity) === edgeIdentity) {
|
|
287
|
+
edgelist.splice(edgeIndex, 1);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
this.emit("edge-removed", edgeIdentity);
|
|
295
|
+
}
|
|
296
|
+
remove(nodeIdentity) {
|
|
297
|
+
if (!this.nodes.has(nodeIdentity)) {
|
|
298
|
+
throw new NodeDoesntExistError(nodeIdentity);
|
|
299
|
+
}
|
|
300
|
+
this.nodes.delete(nodeIdentity);
|
|
301
|
+
const nodeIndex = Array.from(this.nodes.keys()).indexOf(nodeIdentity);
|
|
302
|
+
this.adjacency.splice(nodeIndex, 1);
|
|
303
|
+
this.adjacency.forEach((row) => row.splice(nodeIndex, 1));
|
|
304
|
+
this.emit("node-removed", nodeIdentity);
|
|
305
|
+
}
|
|
306
|
+
removeNode(nodeIdentity) {
|
|
307
|
+
return this.remove(nodeIdentity);
|
|
308
|
+
}
|
|
309
|
+
addNode(node) {
|
|
310
|
+
return this.insert(node);
|
|
311
|
+
}
|
|
312
|
+
addNodes(nodes) {
|
|
313
|
+
return nodes.map((node) => this.insert(node));
|
|
314
|
+
}
|
|
315
|
+
addEdges(edges) {
|
|
316
|
+
return edges.map(([node1Identity, node2Identity, edge]) => this.addEdge(node1Identity, node2Identity, edge));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/graph/directedGraph.ts
|
|
321
|
+
class DirectedGraph extends Graph {
|
|
322
|
+
hasCycle = false;
|
|
323
|
+
isAcyclic() {
|
|
324
|
+
if (this.hasCycle !== undefined) {
|
|
325
|
+
return !this.hasCycle;
|
|
326
|
+
}
|
|
327
|
+
const nodeIndices = Array.from(this.nodes.keys());
|
|
328
|
+
const nodeInDegrees = new Map(Array.from(this.nodes.keys()).map((n) => [n, this.indegreeOfNode(n)]));
|
|
329
|
+
const toSearch = Array.from(nodeInDegrees).filter((pair) => pair[1] === 0);
|
|
330
|
+
let visitedNodes = 0;
|
|
331
|
+
while (toSearch.length > 0) {
|
|
332
|
+
const cur = toSearch.pop();
|
|
333
|
+
if (cur === undefined) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const nodeIndex = nodeIndices.indexOf(cur[0]);
|
|
337
|
+
this.adjacency[nodeIndex].forEach((hasAdj, index) => {
|
|
338
|
+
if (hasAdj !== null) {
|
|
339
|
+
const currentInDegree = nodeInDegrees.get(nodeIndices[index]);
|
|
340
|
+
if (currentInDegree !== undefined) {
|
|
341
|
+
nodeInDegrees.set(nodeIndices[index], currentInDegree - 1);
|
|
342
|
+
if (currentInDegree - 1 === 0) {
|
|
343
|
+
toSearch.push([nodeIndices[index], currentInDegree - 1]);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
visitedNodes++;
|
|
349
|
+
}
|
|
350
|
+
this.hasCycle = !(visitedNodes === this.nodes.size);
|
|
351
|
+
return visitedNodes === this.nodes.size;
|
|
352
|
+
}
|
|
353
|
+
indegreeOfNode(nodeID) {
|
|
354
|
+
const nodeIdentities = Array.from(this.nodes.keys());
|
|
355
|
+
const indexOfNode = nodeIdentities.indexOf(nodeID);
|
|
356
|
+
if (indexOfNode === -1) {
|
|
357
|
+
throw new NodeDoesntExistError(nodeID);
|
|
358
|
+
}
|
|
359
|
+
return this.adjacency.reduce((carry, row) => {
|
|
360
|
+
return carry + (row[indexOfNode] == null ? 0 : 1);
|
|
361
|
+
}, 0);
|
|
362
|
+
}
|
|
363
|
+
addEdge(sourceNodeIdentity, targetNodeIdentity, edge, skipUpdatingCyclicality = false) {
|
|
364
|
+
if (edge === undefined) {
|
|
365
|
+
edge = true;
|
|
366
|
+
}
|
|
367
|
+
if (this.hasCycle === false && !skipUpdatingCyclicality) {
|
|
368
|
+
this.hasCycle = this.wouldAddingEdgeCreateCycle(sourceNodeIdentity, targetNodeIdentity);
|
|
369
|
+
} else if (skipUpdatingCyclicality) {
|
|
370
|
+
this.hasCycle = undefined;
|
|
371
|
+
}
|
|
372
|
+
return super.addEdge(sourceNodeIdentity, targetNodeIdentity, edge);
|
|
373
|
+
}
|
|
374
|
+
canReachFrom(startNode, endNode) {
|
|
375
|
+
const nodeIdentities = Array.from(this.nodes.keys());
|
|
376
|
+
const startNodeIndex = nodeIdentities.indexOf(startNode);
|
|
377
|
+
const endNodeIndex = nodeIdentities.indexOf(endNode);
|
|
378
|
+
if (this.adjacency[startNodeIndex][endNodeIndex] != null) {
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
return this.adjacency[startNodeIndex].reduce((carry, edge, index) => {
|
|
382
|
+
if (carry || edge === null) {
|
|
383
|
+
return carry;
|
|
384
|
+
}
|
|
385
|
+
return this.canReachFrom(nodeIdentities[index], endNode);
|
|
386
|
+
}, false);
|
|
387
|
+
}
|
|
388
|
+
wouldAddingEdgeCreateCycle(sourceNodeIdentity, targetNodeIdentity) {
|
|
389
|
+
return this.hasCycle || sourceNodeIdentity === targetNodeIdentity || this.canReachFrom(targetNodeIdentity, sourceNodeIdentity);
|
|
390
|
+
}
|
|
391
|
+
getSubGraphStartingFrom(startNodeIdentity) {
|
|
392
|
+
const nodeIndices = Array.from(this.nodes.keys());
|
|
393
|
+
const initalNode = this.nodes.get(startNodeIdentity);
|
|
394
|
+
if (initalNode == null) {
|
|
395
|
+
throw new NodeDoesntExistError(startNodeIdentity);
|
|
396
|
+
}
|
|
397
|
+
const recur = (startNodeIdentity2, nodesToInclude) => {
|
|
398
|
+
let toReturn = [...nodesToInclude];
|
|
399
|
+
const nodeIndex = nodeIndices.indexOf(startNodeIdentity2);
|
|
400
|
+
this.adjacency[nodeIndex].forEach((hasAdj, index) => {
|
|
401
|
+
if (hasAdj !== null && nodesToInclude.find((n) => this.nodeIdentity(n) === nodeIndices[index]) == null) {
|
|
402
|
+
const newNode = this.nodes.get(nodeIndices[index]);
|
|
403
|
+
if (newNode != null) {
|
|
404
|
+
toReturn = [...recur(nodeIndices[index], toReturn), newNode];
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
return toReturn;
|
|
409
|
+
};
|
|
410
|
+
const newGraph = new DirectedGraph(this.nodeIdentity, this.edgeIdentity);
|
|
411
|
+
const nodeList = recur(startNodeIdentity, [initalNode]);
|
|
412
|
+
const includeIdents = nodeList.map((t) => this.nodeIdentity(t));
|
|
413
|
+
Array.from(this.nodes.values()).forEach((n) => {
|
|
414
|
+
if (includeIdents.includes(this.nodeIdentity(n))) {
|
|
415
|
+
newGraph.insert(n);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
newGraph.adjacency = this.subAdj(nodeList);
|
|
419
|
+
return newGraph;
|
|
420
|
+
}
|
|
421
|
+
subAdj(include) {
|
|
422
|
+
const includeIdents = include.map((t) => this.nodeIdentity(t));
|
|
423
|
+
const nodeIndices = Array.from(this.nodes.keys());
|
|
424
|
+
return this.adjacency.reduce((carry, cur, index) => {
|
|
425
|
+
if (includeIdents.includes(nodeIndices[index])) {
|
|
426
|
+
return [...carry, cur.filter((_, index2) => includeIdents.includes(nodeIndices[index2]))];
|
|
427
|
+
} else {
|
|
428
|
+
return carry;
|
|
429
|
+
}
|
|
430
|
+
}, []);
|
|
431
|
+
}
|
|
432
|
+
getEdges() {
|
|
433
|
+
return super.getEdges();
|
|
434
|
+
}
|
|
435
|
+
removeEdge(sourceNodeIdentity, targetNodeIdentity, edgeIdentity) {
|
|
436
|
+
super.removeEdge(sourceNodeIdentity, targetNodeIdentity, edgeIdentity);
|
|
437
|
+
this.hasCycle = undefined;
|
|
438
|
+
}
|
|
439
|
+
remove(nodeIdentity) {
|
|
440
|
+
super.remove(nodeIdentity);
|
|
441
|
+
this.hasCycle = undefined;
|
|
442
|
+
}
|
|
443
|
+
addEdges(edges) {
|
|
444
|
+
return super.addEdges(edges);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// src/graph/directedAcyclicGraph.ts
|
|
449
|
+
class DirectedAcyclicGraph extends DirectedGraph {
|
|
450
|
+
_topologicallySortedNodes;
|
|
451
|
+
static fromDirectedGraph(graph) {
|
|
452
|
+
if (!graph.isAcyclic()) {
|
|
453
|
+
throw new CycleError("Can't convert that graph to a DAG because it contains a cycle");
|
|
454
|
+
}
|
|
455
|
+
const toRet = new DirectedAcyclicGraph(graph.nodeIdentity, graph.edgeIdentity);
|
|
456
|
+
toRet.nodes = graph.nodes;
|
|
457
|
+
toRet.adjacency = graph.adjacency;
|
|
458
|
+
return toRet;
|
|
459
|
+
}
|
|
460
|
+
addEdge(sourceNodeIdentity, targetNodeIdentity, edge) {
|
|
461
|
+
if (edge === undefined) {
|
|
462
|
+
edge = true;
|
|
463
|
+
}
|
|
464
|
+
if (this.wouldAddingEdgeCreateCycle(sourceNodeIdentity, targetNodeIdentity)) {
|
|
465
|
+
throw new CycleError(`Can't add edge from ${String(sourceNodeIdentity)} to ${String(targetNodeIdentity)} it would create a cycle`);
|
|
466
|
+
}
|
|
467
|
+
this._topologicallySortedNodes = undefined;
|
|
468
|
+
return super.addEdge(sourceNodeIdentity, targetNodeIdentity, edge, true);
|
|
469
|
+
}
|
|
470
|
+
insert(node) {
|
|
471
|
+
if (this._topologicallySortedNodes !== undefined) {
|
|
472
|
+
this._topologicallySortedNodes = [node, ...this._topologicallySortedNodes];
|
|
473
|
+
}
|
|
474
|
+
return super.insert(node);
|
|
475
|
+
}
|
|
476
|
+
topologicallySortedNodes() {
|
|
477
|
+
if (this._topologicallySortedNodes !== undefined) {
|
|
478
|
+
return this._topologicallySortedNodes;
|
|
479
|
+
}
|
|
480
|
+
const nodeIndices = Array.from(this.nodes.keys());
|
|
481
|
+
const nodeInDegrees = new Map(Array.from(this.nodes.keys()).map((n) => [n, this.indegreeOfNode(n)]));
|
|
482
|
+
const adjCopy = this.adjacency.map((a) => [...a]);
|
|
483
|
+
const toSearch = Array.from(nodeInDegrees).filter((pair) => pair[1] === 0);
|
|
484
|
+
if (toSearch.length === this.nodes.size) {
|
|
485
|
+
const arrayOfNodes = Array.from(this.nodes.values());
|
|
486
|
+
this._topologicallySortedNodes = arrayOfNodes;
|
|
487
|
+
return arrayOfNodes;
|
|
488
|
+
}
|
|
489
|
+
const toReturn = [];
|
|
490
|
+
while (toSearch.length > 0) {
|
|
491
|
+
const n = toSearch.pop();
|
|
492
|
+
if (n === undefined) {
|
|
493
|
+
throw new Error("Unexpected empty array");
|
|
494
|
+
}
|
|
495
|
+
const curNode = this.nodes.get(n[0]);
|
|
496
|
+
if (curNode == null) {
|
|
497
|
+
throw new Error("This should never happen");
|
|
498
|
+
}
|
|
499
|
+
toReturn.push(curNode);
|
|
500
|
+
adjCopy[nodeIndices.indexOf(n[0])]?.forEach((edge, index) => {
|
|
501
|
+
if (edge !== null) {
|
|
502
|
+
adjCopy[nodeIndices.indexOf(n[0])][index] = null;
|
|
503
|
+
const target = nodeInDegrees.get(nodeIndices[index]);
|
|
504
|
+
if (target !== undefined) {
|
|
505
|
+
nodeInDegrees.set(nodeIndices[index], target - 1);
|
|
506
|
+
if (target - 1 === 0) {
|
|
507
|
+
toSearch.push([nodeIndices[index], 0]);
|
|
508
|
+
}
|
|
509
|
+
} else {
|
|
510
|
+
throw new Error("This should never happen");
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
this._topologicallySortedNodes = toReturn;
|
|
516
|
+
return toReturn;
|
|
517
|
+
}
|
|
518
|
+
getSubGraphStartingFrom(startNodeIdentity) {
|
|
519
|
+
return DirectedAcyclicGraph.fromDirectedGraph(super.getSubGraphStartingFrom(startNodeIdentity));
|
|
520
|
+
}
|
|
521
|
+
removeEdge(sourceNodeIdentity, targetNodeIdentity, edgeIdentity) {
|
|
522
|
+
super.removeEdge(sourceNodeIdentity, targetNodeIdentity, edgeIdentity);
|
|
523
|
+
this._topologicallySortedNodes = undefined;
|
|
524
|
+
}
|
|
525
|
+
remove(nodeIdentity) {
|
|
526
|
+
super.remove(nodeIdentity);
|
|
527
|
+
this._topologicallySortedNodes = undefined;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
export {
|
|
531
|
+
NodeDoesntExistError,
|
|
532
|
+
NodeAlreadyExistsError,
|
|
533
|
+
Graph,
|
|
534
|
+
DirectedGraph,
|
|
535
|
+
DirectedAcyclicGraph,
|
|
536
|
+
CycleError
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
//# debugId=1E5D727E61CDDE0164756E2164756E21
|