using System.Text.Json.Nodes; using w4c_workflows.Models.Nodes; namespace w4c_workflows.Services.Nodes.Executors; /// /// Edit-fields node. Two modes: /// - manual: set the listed fields (an array of { name, value }) /// on each item, optionally discarding the fields that were not listed; /// - json: replace the item payload with the resolved jsonOutput. /// Binary attachments pass through unless includeBinary is false. /// public sealed class SetNodeExecutor : INodeExecutor { public string Type => "core.set"; public Task RunAsync(NodeExecutionContext context, CancellationToken ct) { var mode = ReadString(context, "mode") ?? "manual"; var keepOnlySet = ReadBool(context, "keepOnlySet"); var includeBinary = ReadBool(context, "includeBinary", defaultValue: true); var items = context.Input(0); var output = new List(items.Count); foreach (var item in items) { var json = string.Equals(mode, "json", StringComparison.OrdinalIgnoreCase) ? BuildFromJson(context) : ApplyFields(context, item.Json, keepOnlySet); output.Add(new FlowItem { Json = json, Binary = includeBinary ? item.Binary : null, Origin = item.Origin, }); } return Task.FromResult(NodeExecutionOutcome.Single(output)); } private static JsonObject ApplyFields(NodeExecutionContext context, JsonObject source, bool keepOnlySet) { var result = keepOnlySet ? new JsonObject() : (JsonObject)source.DeepClone(); if (context.Parameters["fields"] is not JsonArray fields) return result; foreach (var entry in fields) { if (entry is not JsonObject field) continue; var name = field["name"]?.GetValue(); if (string.IsNullOrWhiteSpace(name)) continue; result[name] = field["value"]?.DeepClone(); } return result; } private static JsonObject BuildFromJson(NodeExecutionContext context) { var value = context.Parameters["jsonOutput"]; if (value is JsonObject obj) return (JsonObject)obj.DeepClone(); return value is null ? new JsonObject() : new JsonObject { ["value"] = value.DeepClone() }; } private static string? ReadString(NodeExecutionContext context, string name) => context.Parameters[name] is JsonValue value && value.TryGetValue(out var text) ? text : null; private static bool ReadBool(NodeExecutionContext context, string name, bool defaultValue = false) => context.Parameters[name] is JsonValue value && value.TryGetValue(out var flag) ? flag : defaultValue; }