w4c-workflows-api/Services/Nodes/Executors/SetNodeExecutor.cs
2026-09-12 01:02:46 +03:00

79 lines
2.9 KiB
C#

using System.Text.Json.Nodes;
using w4c_workflows.Models.Nodes;
namespace w4c_workflows.Services.Nodes.Executors;
/// <summary>
/// Edit-fields node. Two modes:
/// - <c>manual</c>: set the listed <c>fields</c> (an array of <c>{ name, value }</c>)
/// on each item, optionally discarding the fields that were not listed;
/// - <c>json</c>: replace the item payload with the resolved <c>jsonOutput</c>.
/// Binary attachments pass through unless <c>includeBinary</c> is false.
/// </summary>
public sealed class SetNodeExecutor : INodeExecutor
{
public string Type => "core.set";
public Task<NodeExecutionOutcome> 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<FlowItem>(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<string>();
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<string>(out var text) ? text : null;
private static bool ReadBool(NodeExecutionContext context, string name, bool defaultValue = false)
=> context.Parameters[name] is JsonValue value && value.TryGetValue<bool>(out var flag) ? flag : defaultValue;
}