diff --git a/src/ConductorSharp.Toolkit/Commands/Command.cs b/src/ConductorSharp.Toolkit/Commands/Command.cs index 165f6e79..d05dc612 100644 --- a/src/ConductorSharp.Toolkit/Commands/Command.cs +++ b/src/ConductorSharp.Toolkit/Commands/Command.cs @@ -5,6 +5,6 @@ namespace ConductorSharp.Toolkit.Commands public interface Command { public string GetName(); - public Task Execute(CommandInput input); + public Task Execute(Configuration input); } } diff --git a/src/ConductorSharp.Toolkit/Commands/ScaffoldCommand.cs b/src/ConductorSharp.Toolkit/Commands/ScaffoldCommand.cs index 39159cde..7e20f868 100644 --- a/src/ConductorSharp.Toolkit/Commands/ScaffoldCommand.cs +++ b/src/ConductorSharp.Toolkit/Commands/ScaffoldCommand.cs @@ -14,7 +14,7 @@ public ScaffoldCommand(IScaffoldingService scaffoldingService) public string GetName() => "scaffold"; - public async Task Execute(CommandInput input) + public async Task Execute(Configuration input) { await _scaffoldingService.Scaffold(); } diff --git a/src/ConductorSharp.Toolkit/ConductorSharp.Toolkit.csproj b/src/ConductorSharp.Toolkit/ConductorSharp.Toolkit.csproj index bdc8bcc6..e94e30a4 100644 --- a/src/ConductorSharp.Toolkit/ConductorSharp.Toolkit.csproj +++ b/src/ConductorSharp.Toolkit/ConductorSharp.Toolkit.csproj @@ -25,8 +25,10 @@ + + diff --git a/src/ConductorSharp.Toolkit/Models/CommandInput.cs b/src/ConductorSharp.Toolkit/Models/CommandInput.cs deleted file mode 100644 index 19b2d75d..00000000 --- a/src/ConductorSharp.Toolkit/Models/CommandInput.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ConductorSharp.Toolkit.Models -{ - public class CommandInput - { - public string Api { get; set; } - public string Namespace { get; set; } - public string Host { get; set; } - public bool Dryrun { get; set; } - public string Destination { get; set; } - } -} diff --git a/src/ConductorSharp.Toolkit/Models/Configuration.cs b/src/ConductorSharp.Toolkit/Models/Configuration.cs new file mode 100644 index 00000000..9caafdb3 --- /dev/null +++ b/src/ConductorSharp.Toolkit/Models/Configuration.cs @@ -0,0 +1,11 @@ +namespace ConductorSharp.Toolkit.Models +{ + public class Configuration + { + public string ApiPath { get; set; } = "api"; + public string Namespace { get; set; } + public string BaseUrl { get; set; } + public string Destination { get; set; } + public Dictionary Headers { get; set; } = new Dictionary(); + } +} diff --git a/src/ConductorSharp.Toolkit/Models/ToolkitOptions.cs b/src/ConductorSharp.Toolkit/Models/ToolkitOptions.cs new file mode 100644 index 00000000..25a6634e --- /dev/null +++ b/src/ConductorSharp.Toolkit/Models/ToolkitOptions.cs @@ -0,0 +1,10 @@ +using CommandLine; + +namespace ConductorSharp.Toolkit.Models +{ + public class ToolkitOptions + { + [Option('f', "file", HelpText = "Configuration file", Default = "conductorsharp.yaml")] + public string ConfigurationFilePath { get; set; } + } +} diff --git a/src/ConductorSharp.Toolkit/Program.cs b/src/ConductorSharp.Toolkit/Program.cs index f5ddbf01..fed52eff 100644 --- a/src/ConductorSharp.Toolkit/Program.cs +++ b/src/ConductorSharp.Toolkit/Program.cs @@ -4,36 +4,105 @@ using ConductorSharp.Engine.Extensions; using ConductorSharp.Toolkit.Commands; using ConductorSharp.Toolkit.Models; +using CommandLine; +using CommandLine.Text; +using System.Reflection; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; +using RestSharp; +using RestSharp.Serializers.NewtonsoftJson; namespace ConductorSharp.Toolkit { class Program { + public const string Version = "0.0.1"; + public async static Task Main(string[] args) { - try + var parseResult = new Parser(opts => opts.HelpWriter = null).ParseArguments(args); + var withParsed = await parseResult.WithParsedAsync(RunToolkit); + withParsed.WithNotParsed(err => { - var action = args[0]; + var versionText = new HeadingInfo("conductorsharp", Version); + var writer = err.IsHelp() || err.IsVersion() ? Console.Out : Console.Error; + string textToWrite; + if (err.IsVersion()) + textToWrite = versionText; + else + { + textToWrite = HelpText.AutoBuild( + parseResult, + help => + { + help.Copyright = new CopyrightInfo("Codaxy", 2022); + help.AddPreOptionsLine("Usage: dotnet conductorsharp [options]"); + help.Heading = versionText; + return help; + } + ); + } + + writer.WriteLine(textToWrite); + }); + } - var input = ParseInput(args); + private static async Task RunToolkit(ToolkitOptions options) + { + try + { + if (!File.Exists(options.ConfigurationFilePath)) + { + Console.Error.WriteLine($"Configuration file {options.ConfigurationFilePath} does not exists"); + return; + } - var container = BuildContainer(input); + var config = ParseConfigurationFile(options.ConfigurationFilePath); + if (!ValidateConfiguration(config)) + return; + var container = BuildContainer(config); var commandRegistry = container.Resolve(); + // Currently only scaffolding is supported + var command = commandRegistry.Get("scaffold"); + await command.Execute(config); + } + // TODO: Improve error handling + catch (Exception ex) + { + Console.Error.WriteLine($"Exception occured with message: {ex.Message}"); + } + } - var command = commandRegistry.Get(action); + private static Configuration ParseConfigurationFile(string configFilePath) => + new DeserializerBuilder() + .WithNamingConvention(CamelCaseNamingConvention.Instance) + .Build() + .Deserialize(File.ReadAllText(configFilePath)); - await command.Execute(input); + private static bool ValidateConfiguration(Configuration config) + { + bool validConfiguration = true; + if (string.IsNullOrEmpty(config.BaseUrl)) + { + Console.Error.WriteLine("baseUrl property missing in configuration"); + validConfiguration = false; } - catch (Exception exc) + if (string.IsNullOrEmpty(config.Namespace)) { - PrintHelp(); + Console.Error.WriteLine("namespace property missing in configuration"); + validConfiguration = false; + } + if (string.IsNullOrEmpty(config.Destination)) + { + Console.Error.WriteLine("destination property missing in configuration"); + validConfiguration = false; } - } - private static void PrintHelp() => Console.WriteLine("PLACEHOLDER HELP"); + return validConfiguration; + } - private static IContainer BuildContainer(CommandInput input) + private static IContainer BuildContainer(Configuration config) { var serviceCollection = new ServiceCollection(); @@ -41,35 +110,29 @@ private static IContainer BuildContainer(CommandInput input) var builder = new ContainerBuilder(); - serviceCollection.Configure(config => + serviceCollection.Configure(scaffoldingConfig => { - config.ApiUrl = input.Api; - config.BaseUrl = input.Host; - config.BaseNamespace = input.Namespace; - config.Dryrun = input.Dryrun; - config.Destination = input.Destination; + scaffoldingConfig.ApiUrl = config.ApiPath; + scaffoldingConfig.BaseUrl = config.BaseUrl; + scaffoldingConfig.BaseNamespace = config.Namespace; + scaffoldingConfig.Destination = config.Destination; }); builder.Populate(serviceCollection); - builder.AddWorkflowEngine(input.Host, input.Api); + builder.AddWorkflowEngine( + config.BaseUrl, + config.ApiPath, + createClient: () => + { + var client = new RestClient(); + client.UseNewtonsoftJson(); + client.AddDefaultHeaders(config.Headers); + return client; + } + ); builder.RegisterModule(new ToolkitModule()); return builder.Build(); } - - private static CommandInput ParseInput(string[] args) - { - var action = args[0]; - var inputParameters = args.Skip(1).Select(a => new KeyValuePair(a.Split("=")[0], a.Split("=")[1])).ToList(); - - return new CommandInput - { - Api = inputParameters.Where(a => a.Key == "path").Select(a => a.Value).FirstOrDefault(), - Namespace = inputParameters.Where(a => a.Key == "namespace").Select(a => a.Value).FirstOrDefault(), - Host = inputParameters.Where(a => a.Key == "host").Select(a => a.Value).FirstOrDefault(), - Dryrun = inputParameters.Where(a => a.Key == "dryrun").Select(a => bool.Parse(a.Value)).FirstOrDefault(), - Destination = inputParameters.Where(a => a.Key == "destination").Select(a => a.Value).FirstOrDefault() - }; - } } }