* Given a starting node and a function for finding connected nodes, walks the graph and * finds all connected nodes.
(startingId: string, walkFn: GraphlibRelations)
| 18 | * finds all connected nodes. |
| 19 | */ |
| 20 | function walkGraph(startingId: string, walkFn: GraphlibRelations) { |
| 21 | const results = new Set<string>(); |
| 22 | const visited = new Set<string>(); |
| 23 | const toVisit = [startingId]; |
| 24 | // We iterate until we don't find any more nodes, then return |
| 25 | while (toVisit.length > 0) { |
| 26 | const next = toVisit.pop(); |
| 27 | // we know this will be defined because of the length check in the while condition |
| 28 | assert(next); |
| 29 | // because there might be mutliple edges that lead to the same node, we guard against |
| 30 | // walking the same node more than once. |
| 31 | if (visited.has(next)) continue; |
| 32 | visited.add(next); |
| 33 | |
| 34 | const found = walkFn(next); |
| 35 | if (!found) continue; |
| 36 | |
| 37 | for (const id of found) { |
| 38 | toVisit.push(id); |
| 39 | results.add(id); |
| 40 | } |
| 41 | } |
| 42 | return Array.from(results.values()); |
| 43 | } |
| 44 | |
| 45 | export const getUpstreamNodes = (id: string, graph: dagre.graphlib.Graph) => |
| 46 | walkGraph(id, graph.predecessors.bind(graph) as unknown as GraphlibRelations); |