using Microsoft.AspNetCore.Mvc; using w4c_workflows.Filters; using w4c_workflows.Models.Nodes; using w4c_workflows.Services.Nodes; namespace w4c_workflows.Controllers; /// /// Node catalog surface. The authoring UI uses this to render its palette and /// its generic parameter forms; it authenticates with the tenant operator key /// like the rest of the control plane. /// [ApiController] [Route("api/nodes")] public class NodesController : ControllerBase { private readonly NodeBlueprintCatalog _catalog; private readonly NodeExecutorRegistry _executors; public NodesController(NodeBlueprintCatalog catalog, NodeExecutorRegistry executors) { _catalog = catalog; _executors = executors; } /// Lists node types for the palette, with optional search/filter. [HttpGet] [RequireScope("read")] public IActionResult List( [FromQuery] string? search, [FromQuery] string? kind, [FromQuery] string? category, [FromQuery] bool includeHidden = false) { var results = _catalog.Search(search, kind, category); if (!includeHidden) results = results.Where(b => !b.Hidden).ToList(); return Ok(results.Select(Summarize)); } /// All category labels, for the palette's category rail. [HttpGet("categories")] [RequireScope("read")] public IActionResult Categories() => Ok(_catalog.Categories); /// Full blueprint for one node type (optionally a pinned version). [HttpGet("{type}")] [RequireScope("read")] public IActionResult Get(string type, [FromQuery] double? version) { var blueprint = _catalog.Resolve(type, version); if (blueprint is null) return NotFound(new { error = $"unknown node type '{type}'" }); return Ok(new NodeDetail(blueprint, _executors.CanRun(blueprint.Type))); } private NodeSummary Summarize(NodeBlueprint blueprint) => new( blueprint.Type, blueprint.Version, blueprint.DisplayName, blueprint.Description, blueprint.Kind, blueprint.Categories, blueprint.Icon, blueprint.IconColor, blueprint.RunMode, blueprint.Hidden, blueprint.Origin, blueprint.Inputs.Count, blueprint.Outputs.Count, blueprint.Inputs, blueprint.Outputs, blueprint.ProducesErrorBranch, blueprint.Credentials.Any(c => c.Required), _executors.CanRun(blueprint.Type)); } /// Palette entry: blueprint identity plus port shape, without the full form schema. public sealed record NodeSummary( string Type, double Version, string DisplayName, string? Description, string Kind, IReadOnlyList Categories, string? Icon, string? IconColor, string RunMode, bool Hidden, string Origin, int Inputs, int Outputs, IReadOnlyList InputPorts, IReadOnlyList OutputPorts, bool HasErrorBranch, bool RequiresCredentials, bool Runnable); /// Full blueprint detail plus whether an executor is installed for it. public sealed record NodeDetail(NodeBlueprint Blueprint, bool Runnable);