diff --git a/source/Cli/CreativeCoders.Cli.Core/CommandResult.cs b/source/Cli/CreativeCoders.Cli.Core/CommandResult.cs index 4b4b3c32..ca1e8e15 100644 --- a/source/Cli/CreativeCoders.Cli.Core/CommandResult.cs +++ b/source/Cli/CreativeCoders.Cli.Core/CommandResult.cs @@ -2,9 +2,17 @@ namespace CreativeCoders.Cli.Core; +/// +/// Represents the result of executing a command. +/// [PublicAPI] public class CommandResult { + /// + /// Represents a successful result of a command execution with an implicit default exit code of 0. + /// + public static CommandResult Success { get; } = new CommandResult(); + public CommandResult() { } public CommandResult(int exitCode) @@ -13,4 +21,9 @@ public CommandResult(int exitCode) } public int ExitCode { get; init; } + + public static implicit operator CommandResult(int exitCode) + => exitCode == 0 + ? Success + : new CommandResult(exitCode); } diff --git a/source/Cli/CreativeCoders.Cli.Core/ICliCommandContext.cs b/source/Cli/CreativeCoders.Cli.Core/ICliCommandContext.cs index f9f9071a..fb864c3e 100644 --- a/source/Cli/CreativeCoders.Cli.Core/ICliCommandContext.cs +++ b/source/Cli/CreativeCoders.Cli.Core/ICliCommandContext.cs @@ -2,10 +2,21 @@ namespace CreativeCoders.Cli.Core; +/// +/// Represents the context for a CLI command, providing access to arguments passed to the command. +/// [PublicAPI] public interface ICliCommandContext { + /// + /// Gets or sets all arguments passed to the CLI app, including commands, options and positional arguments. + /// This property provides full visibility of the input arguments passed to the CLI app for further processing. + /// public string[] AllArgs { get; set; } + /// + /// Gets or sets the arguments that represent options passed to the CLI command. + /// This property contains only the arguments classified as options and excludes CLI inputs such as commands. + /// public string[] OptionsArgs { get; set; } } diff --git a/source/Cli/CreativeCoders.Cli.Core/OptionsValidationResult.cs b/source/Cli/CreativeCoders.Cli.Core/OptionsValidationResult.cs index 523d2f72..562c03eb 100644 --- a/source/Cli/CreativeCoders.Cli.Core/OptionsValidationResult.cs +++ b/source/Cli/CreativeCoders.Cli.Core/OptionsValidationResult.cs @@ -16,4 +16,27 @@ public class OptionsValidationResult(bool isValid, IEnumerable? messages /// Gets the validation messages. /// public IEnumerable Messages { get; } = messages ?? []; + + /// + /// Creates a predefined valid result for options validation where + /// the validation is successful without any messages. + /// + /// + /// An instance representing a successful validation result + /// with an empty collection of messages. + /// + public static OptionsValidationResult Valid() => new OptionsValidationResult(true); + + /// + /// Creates a predefined invalid result for options validation where + /// the validation fails and may include associated validation messages. + /// + /// An optional collection of validation messages explaining the failure. + /// If null, the result will contain an empty collection of messages. + /// + /// An instance representing an unsuccessful validation result + /// with the provided validation messages or an empty collection if none are specified. + /// + public static OptionsValidationResult Invalid(IEnumerable? messages) + => new OptionsValidationResult(false, messages); } diff --git a/source/Cli/CreativeCoders.Cli.Hosting/ICliHost.cs b/source/Cli/CreativeCoders.Cli.Hosting/ICliHost.cs index 1e235cd0..c083b8c1 100644 --- a/source/Cli/CreativeCoders.Cli.Hosting/ICliHost.cs +++ b/source/Cli/CreativeCoders.Cli.Hosting/ICliHost.cs @@ -1,7 +1,16 @@ namespace CreativeCoders.Cli.Hosting; +/// +/// Represents a Command Line Interface (CLI) host that provides functionality to execute +/// commands and handle related tasks. +/// public interface ICliHost { + /// + /// Executes the CLI host with the given arguments and returns the result of the operation. + /// + /// The command line arguments provided to the host. + /// A object containing the exit code of the executed command. Task RunAsync(string[] args); /// diff --git a/source/Cli/CreativeCoders.Cli.Hosting/ICliHostBuilder.cs b/source/Cli/CreativeCoders.Cli.Hosting/ICliHostBuilder.cs index 53b1438c..657959fa 100644 --- a/source/Cli/CreativeCoders.Cli.Hosting/ICliHostBuilder.cs +++ b/source/Cli/CreativeCoders.Cli.Hosting/ICliHostBuilder.cs @@ -6,16 +6,54 @@ namespace CreativeCoders.Cli.Hosting; +/// +/// Defines a builder for configuring and creating an instance of . +/// Provides methods to set up services, command context, assembly scanning, validation, and help functionality +/// for a Command Line Interface (CLI) application. +/// [PublicAPI] public interface ICliHostBuilder { + /// + /// Configures a custom command context for the CLI application. + /// + /// The type of the context to be used. Must implement . + /// + /// An optional action to configure the context instance. The action receives the service provider + /// and the instance of as parameters. + /// + /// The same instance. + /// Thrown if the context is already configured. ICliHostBuilder UseContext(Action? configure = null) where TContext : class, ICliCommandContext; + /// + /// Configures additional services for the CLI application. + /// + /// + /// An action that receives an to add or modify services for the application. + /// + /// The same instance, enabling method chaining. + /// Thrown if is null. ICliHostBuilder ConfigureServices(Action configureServices); + /// + /// Registers specified assemblies for command scanning within the CLI application. + /// + /// + /// An array of instances to be scanned for commands. + /// + /// The same instance. ICliHostBuilder ScanAssemblies(params Assembly[] assemblies); + /// + /// Enables help functionality for the CLI application by specifying the type of help commands to be supported. + /// + /// + /// Defines the type of help commands that can be used within the application. + /// This can be a command-specific help, argument-specific help, or both, as specified by the values in . + /// + /// The same instance to allow for method chaining. ICliHostBuilder EnableHelp(HelpCommandKind commandKind); /// @@ -25,7 +63,21 @@ ICliHostBuilder UseContext(Action? configu /// The same instance. ICliHostBuilder UseValidation(bool useValidation = true); + /// + /// Specifies whether the entry assembly should be excluded from the scanning process + /// when configuring the CLI application. + /// + /// + /// A boolean value indicating whether to skip scanning the entry assembly. Defaults to true. + /// If set to false, the entry assembly will be included in the assembly scanning process. + /// + /// The same instance. ICliHostBuilder SkipScanEntryAssembly(bool skipScanEntryAssembly = true); + /// + /// Builds and creates an instance of configured through the current builder. + /// + /// An instance of that represents the configured Command Line Interface (CLI) application. + /// Thrown if the build process encounters an invalid state or configuration. ICliHost Build(); } diff --git a/tests/CreativeCoders.Cli.Tests/Core/CommandResultTests.cs b/tests/CreativeCoders.Cli.Tests/Core/CommandResultTests.cs new file mode 100644 index 00000000..c665226c --- /dev/null +++ b/tests/CreativeCoders.Cli.Tests/Core/CommandResultTests.cs @@ -0,0 +1,35 @@ +using AwesomeAssertions; +using CreativeCoders.Cli.Core; +using Xunit; + +namespace CreativeCoders.Cli.Tests.Core; + +public class CommandResultTests +{ + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(-1)] + [InlineData(int.MaxValue)] + [InlineData(int.MinValue)] + public void ImplicitOperator_FromInt_CreatesCommandResultWithExitCode(int exitCode) + { + // Act + var result = (CommandResult)exitCode; + + // Assert + result.ExitCode + .Should().Be(exitCode); + } + + [Fact] + public void Success_ReturnsResultWithExitCodeZero() + { + // Act + var result = CommandResult.Success; + + // Assert + result.ExitCode + .Should().Be(0); + } +} diff --git a/tests/CreativeCoders.Cli.Tests/Core/OptionsValidationResultTests.cs b/tests/CreativeCoders.Cli.Tests/Core/OptionsValidationResultTests.cs new file mode 100644 index 00000000..c24f9042 --- /dev/null +++ b/tests/CreativeCoders.Cli.Tests/Core/OptionsValidationResultTests.cs @@ -0,0 +1,56 @@ +using AwesomeAssertions; +using CreativeCoders.Cli.Core; +using Xunit; + +namespace CreativeCoders.Cli.Tests.Core; + +public class OptionsValidationResultTests +{ + [Fact] + public void StaticValid_Call_ReturnsValidResult() + { + // Act + var result = OptionsValidationResult.Valid(); + + // Assert + result.IsValid + .Should().BeTrue(); + + result.Messages + .Should().BeEmpty(); + } + + [Fact] + public void StaticInvalid_Call_ReturnsInvalidResultWithMessages() + { + // Arrange + const string message0 = "Test"; + const string message1 = "qwertz2"; + + var messages = new[] { message0, message1 }; + + // Act + var result = OptionsValidationResult.Invalid(messages); + + // Assert + result.IsValid + .Should().BeFalse(); + + result.Messages + .Should().BeEquivalentTo(message0, message1); + } + + [Fact] + public void StaticInvalid_CallWithMessagesNull_ReturnsInvalidResultWithEmptyMessages() + { + // Act + var result = OptionsValidationResult.Invalid(null); + + // Assert + result.IsValid + .Should().BeFalse(); + + result.Messages + .Should().BeEmpty(); + } +}