import { TaskDefinition } from "../services/WorkflowTemplateService"; export const getAllDescendants = ( guid: string, tasks: TaskDefinition[], ): Set => { const descendants = new Set(); const visit = (current: string) => { for (const t of tasks) { const preds = (t.config.predecessors as string[]) ?? []; // If t depends on current, it's a child if ( preds.includes(current) && !descendants.has(t.config.guid as string) ) { const childGuid = t.config.guid as string; descendants.add(childGuid); visit(childGuid); // recursively find grandchildren } } }; visit(guid); return descendants; }; export const sortTasksTopologically = ( tasks: TaskDefinition[], ): TaskDefinition[] => { // Build adjacency list: task -> its predecessors const preds = new Map(); const byId = new Map(); tasks.forEach((t) => { const guid = t.config.guid as string; byId.set(guid, t); preds.set(guid, (t.config.predecessors as string[]) ?? []); }); const result: TaskDefinition[] = []; const visited = new Set(); const temp = new Set(); // for cycle detection (should never trigger now) const visit = (guid: string) => { if (visited.has(guid)) return; if (temp.has(guid)) throw new Error("Cycle detected unexpectedly"); temp.add(guid); for (const p of preds.get(guid) ?? []) { visit(p); } temp.delete(guid); visited.add(guid); result.push(byId.get(guid)!); }; // Visit all tasks tasks.forEach((t) => visit(t.config.guid as string)); return result; };