using System.CommandLine; using System.CommandLine.Parsing; using System.Text.Json; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// CLI adapters for the shared JSON schema library management contracts. public static class SharedSchemaCommands { /// Builds the shared-schema list/get/create/update/delete command group. /// Management URL option. /// Output format option. /// Authentication username option. /// Authentication password option. /// The configured shared-schema group. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var group = new Command("shared-schema") { Description = "Manage the shared JSON schema library" }; var list = new Command("list") { Description = "List shared schemas" }; list.SetAction((ParseResult result) => Send(result, new ListSharedSchemasCommand())); group.Add(list); group.Add(BuildIdentity("get", id => new GetSharedSchemaCommand(id))); group.Add(BuildEdit(update: false)); group.Add(BuildEdit(update: true)); group.Add(BuildIdentity("delete", id => new DeleteSharedSchemaCommand(id))); return group; Task Send(ParseResult result, object command) => CommandHelpers.ExecuteCommandAsync( result, urlOption, formatOption, usernameOption, passwordOption, command); Command BuildIdentity(string verb, Func makeCommand) { var id = new Option("--id") { Description = "Shared schema ID", Required = true }; var command = new Command(verb) { Description = $"{(verb == "get" ? "Get" : "Delete")} a shared schema by ID" }; command.Add(id); command.SetAction((ParseResult result) => Send(result, makeCommand(result.GetValue(id)))); return command; } Command BuildEdit(bool update) { var id = new Option("--id") { Description = "Shared schema ID", Required = true }; var name = new Option("--name") { Description = "Schema library name", Required = true }; var scope = new Option("--scope") { Description = "Optional schema scope; omission clears scope on update" }; var file = new Option("--schema-file") { Description = "Path to the JSON schema document", Required = true }; var command = new Command(update ? "update" : "create") { Description = update ? "Replace a shared schema's name, scope, and JSON document" : "Create a shared schema from a JSON file" }; if (update) command.Add(id); command.Add(name); command.Add(scope); command.Add(file); command.SetAction(async (ParseResult result) => { string json; try { json = await File.ReadAllTextAsync(result.GetValue(file)!); using var parsed = JsonDocument.Parse(json); } catch (JsonException ex) { OutputFormatter.WriteError($"Invalid schema JSON: {ex.Message}", "INVALID_JSON"); return 1; } catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or ArgumentException) { OutputFormatter.WriteError($"Could not read schema file: {ex.Message}", "FILE_ERROR"); return 1; } // Structural schema validation, uniqueness, and authorization remain server-owned. object request = update ? new UpdateSharedSchemaCommand(result.GetValue(id), result.GetValue(name)!, result.GetValue(scope), json) : new CreateSharedSchemaCommand(result.GetValue(name)!, result.GetValue(scope), json); return await Send(result, request); }); return command; } } }