using System.Text.Json.Nodes; using w4c_workflows.Models.Credentials; using w4c_workflows.Models.Nodes; using w4c_workflows.Services.Nodes.Interpolation; using w4c_workflows.Services.Security; namespace w4c_workflows.Services.Nodes; // Result-shaping half of the graph runner: normalising the produced ports to the // blueprint's output count, stamping provenance, allocating input ports and // freezing the collected outputs into an immutable run result. public sealed partial class NodeGraphRunner { // ------------------------------------------------------------------ shaping private static List> StampAndNormalize( IReadOnlyList> produced, NodeGraphNode node, int runIndex) { var portCount = Math.Max(1, node.Blueprint.Outputs.Count); var ports = new List>(portCount); for (var port = 0; port < portCount; port++) { var items = port < produced.Count ? produced[port] : Array.Empty(); var stamped = new List(items.Count); for (var index = 0; index < items.Count; index++) { var item = items[index]; stamped.Add(item.Origin == null ? item with { Origin = new FlowItemOrigin(node.Id, port, runIndex, index) } : item); } ports.Add(stamped); } return ports; } private static List[] NewInputPorts(NodeGraphNode node) { var ports = new List[Math.Max(1, node.Blueprint.Inputs.Count)]; for (var i = 0; i < ports.Length; i++) ports[i] = new List(); return ports; } private static IReadOnlyDictionary>> Freeze( IReadOnlyDictionary>> outputs) => outputs.ToDictionary( pair => pair.Key, pair => (IReadOnlyList>)pair.Value, StringComparer.Ordinal); private static NodeGraphRunResult Failure( IReadOnlyDictionary>> outputs, IReadOnlyList order, NodeFailure failure) => new() { OutputsByNode = Freeze(outputs), ExecutionOrder = order.ToList(), Failure = failure, }; }