logo
logo

Walkthrough

This section walks you through the following actions:

  1. Create a project
  2. Create the plugin
  3. Create a command
  4. Register the command

Create a project

Note

The following examples use the .NET Core CLI, but you can achieve the same results using the equivalent functionality in your preferred IDE.

A CLI plugin is simply a class library. To create a class library execute the following commands:

> mkdir Walkthrough
> cd Walkthrough
> dotnet new classlib --framework netcoreapp3.1

After the project is created, you must add a reference to a core CLI functionality:

dotnet add package Sitecore.CH.Cli.Core --source https://slpartners.myget.org/F/m-public/api/v3/index.json

Sitecore.CH.Cli.Core provides access to the plugin infrastructure, useful utilities around file system access, configuration management, and console output as well as a dependency to the Web Client SDK.

Create the plugin

During the application startup, the CLI scans the plugins search paths for types that inherit from Sitecore.CH.Cli.Core.Abstractions.Infrastructure.IPlugin.

Create a new class in the previously created project:

using Sitecore.CH.Cli.Core.Abstractions.Infrastructure;

namespace Walkthrough
{
    public class WalkthroughPlugin : IPlugin
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }

        public void RegisterCommands(ICommandRegistry registry)
        {
        }
    }
}
  • ConfigureServices - Allows to register custom services in the shared service collection and resolve them again at a later point during the command execution.
  • RegisterCommands - Registers new commands that are being delivered as part of this plugin and makes them available through the CLI.

Create a command

When it comes to writing the actual commands there are two possible paths to take:

  • Separate command declaration and command handling. This is the preferred approach as it allows for better and easier unit testing of the command handler implementation:

    using Sitecore.CH.Cli.Core.Abstractions.Commands;
    using Sitecore.CH.Cli.Core.Abstractions.IO;
    
    namespace Walkthrough
    {
        public class EchoCommand : BaseCommand<EchoCommandHandler>
        {
            public EchoCommand() : base("echo")
            {
                // Arguments
                AddArgument(new Argument<string>("value"));
            }
        }
    
        public class EchoCommandHandler : ICommandHandler
        {
            private readonly IConsoleOutput _consoleOutput;
    
            // Inject services from service provider
            public EchoCommand(IConsoleOutput consoleOutput)
            {
                _consoleOutput = consoleOutput;
            }
    
            public string Value { get; set; }
    
            // Command handling
            public Task<int> InvokeAsync(InvocationContext context)
            {
                _consoleOutput.WriteLine(Value);
            }
        }
    }
    
  • Specify arguments, options, and command handling in the same class:

    using Sitecore.CH.Cli.Core.Abstractions.Commands;
    using Sitecore.CH.Cli.Core.Abstractions.IO;
    
    namespace Walkthrough
    {
        public class EchoCommand : BaseCommand
        {
            public EchoCommand() : base("echo")
            {
                // Arguments
                AddArgument(new Argument<string>("value"));
    
                // Command handling
                Handler = CommandHandler.Create<string, IHost>((value, host) =>
                {
                    host.Services.GetService<IConsoleOutput>().WriteLine(value);
                });
            }
        }
    }
    

    In this case, arguments are passed into the function. IHost contains a reference to the service provider that resolves previously registered services.

In both cases the value "echo" that is passed to the base constructor is the name under which the command will be made available later.

Register the command

Now that the plugin class and the command itself are created, they need to be connected. For that you need to go back to the previously created plugin class and add the following to the RegisterCommands method:

registry.RegisterCommandGroup(
    "walkthrough",
    new List<Command>
    {
        new EchoCommand()
    },
    "Walkthrough plugin for demonstration purposes only");

A command group is a way to structure your commands by area or context. Some examples for out-of-the-box command groups are:

  • app
  • audit
  • content
  • jobs
  • orders
  • queues

New commands can be either added to a new command group using the command above or added to an existing one (app in this example) using the following code:

registry.RegisterCommand("app", new EchoCommand());

If you used a separate command handler, add it to the service collection in the ConfigureServices method using the following code:

services.AddTransient(typeof(EchoCommandHandler));

Once compiled and copied to a discoverable plugin search path, the command group and command are included in the CLI help.

This should return the newly added command group amongst the existing ones:

ch-cli --help

This should return the echo command as part of the walkthrough command group:

ch-cli walkthrough --help

Can we improve this article ? Provide feedback