( blocks: Iterable<FlattenOutputsBlockInput>, edges: Iterable<FlattenOutputsEdgeInput> )
| 163 | * of `flattenWorkflowOutputs` (which sorts terminal-blocks-first for picker UX). |
| 164 | */ |
| 165 | export function getBlockExecutionOrder( |
| 166 | blocks: Iterable<FlattenOutputsBlockInput>, |
| 167 | edges: Iterable<FlattenOutputsEdgeInput> |
| 168 | ): Record<string, number> { |
| 169 | const blockList = Array.from(blocks) |
| 170 | const startBlock = blockList.find( |
| 171 | (b) => b.type === 'starter' || b.type === 'start_trigger' || !!b.triggerMode |
| 172 | ) |
| 173 | const distances: Record<string, number> = {} |
| 174 | for (const b of blockList) { |
| 175 | if (b?.id) distances[b.id] = -1 |
| 176 | } |
| 177 | if (!startBlock) return distances |
| 178 | |
| 179 | const adj: Record<string, string[]> = {} |
| 180 | for (const e of edges) { |
| 181 | if (!adj[e.source]) adj[e.source] = [] |
| 182 | adj[e.source].push(e.target) |
| 183 | } |
| 184 | const visited = new Set<string>() |
| 185 | const queue: Array<[string, number]> = [[startBlock.id, 0]] |
| 186 | while (queue.length > 0) { |
| 187 | const [id, d] = queue.shift()! |
| 188 | if (visited.has(id)) continue |
| 189 | visited.add(id) |
| 190 | distances[id] = d |
| 191 | for (const t of adj[id] ?? []) queue.push([t, d + 1]) |
| 192 | } |
| 193 | return distances |
| 194 | } |
no test coverage detected