The Slate Kit CLI is a Command Line Interface application that provides
pre-built functionality for you to integrate your own commands in an interactie manner. This CLI offers 2 distinct approaches to integration. The first approach allows you to handle the raw text supplied in the CLI yourself and is the most flexible. The second approach provides a more connected, automatic experience by exposing, validating, and executing inputs against Slate Kit Universal APIs. You can create a CLI app quickly using the Slate Kit command line executable with the command below.
    
    slatekit new cli -name="SampleCLI" -package="mycompany.apps"
    | Goal | Description | 
| 1. Pre-Built CLI | Support for raw text, parsing, looping, formats, param types | 
| 2. Flexible Use | Handle raw requests or leverage existing integration | 
| 3. API Support | Slate Kit APIs are accessible on Web or CLI | 
This component is currently stable and there is a project generator for it.
A small future enhancement will add support for question and answer flow.
Use the following settings in gradle for installing this component.
    
    buildscript {
        // Kotlin version currently being used
        ext.kotlin_version = '1.8.22'
        // Reference version 
        ext.kiit_version = '3.1.0'
        // ...
    }
    repositories {
        // Currently stored in Git Hub Packages.
        maven {
            url "https://maven.pkg.github.com/slatekit/kiit"
            credentials {
                username = System.getenv('GIT_PACKAGES_INSTALL_ACTOR')
                password = System.getenv('GIT_PACKAGES_INSTALL_TOKEN')
            }
        }
        // ...
    }
    dependencies {
        // Other dependencies ...
        implementation "dev.kiit:kiit-cli:$kiit_version"
    }
    
| Jar | slatekit.cli.jar | 
| Package | slatekit.cli | 
| Sources | slatekit-cli | 
| Example | Example_CLI.kt | 
| Requires | See build.gradle for more info. | 
You can create a custom CLI by extending the Slate Kit CLI component or the CliAPI component which integrates nicely with Slate Kit APIs
     
    import kotlinx.coroutines.runBlocking
    import slatekit.results.*
    import slatekit.cli.CLI
    import slatekit.cli.CliRequest
    import slatekit.cli.CliSettings
    import slatekit.cli.CliResponse 
    class AppCLI(settings: CliSettings, serializer:(Any?, ContentType) -> Content) 
        : CLI(settings, Info.none, Folders.default, serializer = serializer) {
        /**
         * Use case 3a : ( OPTIONAL ) do some stuff before running any commands
         */
        override suspend fun init(): Try<Boolean> {
            // You don't need to override this as the base method displays help info
            context.help.showHelp()
            context.writer.highlight("\thook: onShellStart - starting myapp command line interface")
            return Success(true)
        }
        /**
         * Use case 3b : ( OPTIONAL ) do some stuff before ending the shell this is called
         */
        override suspend fun end(status: Status): Try<Boolean> {
            context.writer.highlight("\thook: onShellEnd - ending myapp command line interface")
            return Success(true)
        }
        /**
         * Handle execution of the CLI Request
         */
        override suspend fun executeRequest(request: CliRequest): Try<CliResponse<*>> {
            // Access the arguments
            val title = request.args.getString("title"))
            val date = request.args.getString("date"))
            
            // Do something with the request
            val res = Success("Processed " + request.path)
            // 4. Now return the response
            return res
        }
    }
    // Serialization for output ( using Slate Kit default )
    val serializer = { item:Any?, type: ContentType -> Content.csv(slatekit.meta.Serialization.csv().serialize(item) )}
    // Create with default settings
    val cli = AppCLI(CliSettings(), serializer)
    // Begin the REPL (Read, Eval, Print, Loop )
    runBlocking {
        cli.run()
    }| Component | Description | 
| CLI | The main component managing the interaction | 
| CliRequest | Represents the command entered | 
| CliResponse | Represents the output of the operation | 
| CliApi | Extends the CLI by integrating it with Slate Kit APIs | 
| Command | Reserved commands like **about, version, help, quit, exit**, etc | 
| Input Param | Parameter starting with **-** representing data for a command | 
| Meta Param | Parameter starting with **@** representing metadata for a command | 
| System Param | Parameter starting with **$** representing an instruction for the CLI | 
| 9. Reference | Reference to command originating from a file | 
| Name | Description | More | 
| 1. Inputs | Handling text and inputs | more | 
| 2. Reserved | List of reserved commands | more | 
| 3. Args | How to convert raw text into parsed parameters | more | 
| 4. Requests | Working with parsed commands as CLI Requests | more | 
| 5. Execute | How to execute a request | more | 
| 6. Responses | Working with parsed commands as CLI Requests | more | 
| 7. Startup | Load a command at start up | more | 
| 8. API | How to access APIs on the command line | more | 
| 9. From file | Load a command from a file | more | 
| 10. Scripts | Run a series of commands in batch mode | more | 
You can customize the CLI so that you can handle a) raw text / lines, b)have the text parsed into arguments, or c) have the text be converted and called as an API request. All these are valid depending on your configuration.
     
    # Handle any text yourself
    :> some free form text
    # Use a arguments style structure
    :> -email="user1@abc.com" -betaUser=true -promoCode=referral
    # Leverage use of Slate Kit Universal APIs by specifying the 3 part route
    :> manage.movies.createSample -title="Dark Knight" -date="2013-07-18"There are several built-in reserved commands. See Reserved.kt for more info
| Text | Aliases | Purpose | 
| exit | quit | Exits the CLI | 
| version | n/a | Gets the current version of the CLI | 
| about | help, info | Gets help text about the CLI and how to use commands | 
The raw text / line is parsed into command line args using the Args
    
    # Leverage use of Slate Kit Universal APIs by specifying the 3 part route
    :> manage.movies.createSample -title="Dark Knight" -date="2013-07-18"
    
    args.getString("title")
    args.getLocalDate("date")The raw text line, after being parsed into command line arguments is converted into a CliRequest object which you can then use to execute your commands.
    /**
     * Handle execution of the CLI Request
     */
    override suspend fun executeRequest(request: CliRequest): Try<CliResponse<*>> {
        // 1. Here is where you can put in your code to handle the command.
        println("running command")
        // 2. You have access to all the command fields and arguments.
        // NOTES: 
        // - The command is parsed into [slatekit.common.args.Args] 
        // - The Args component is put inside [slatekit.cli.CliRequest] 
        // This gets you the raw text/line
        println("line   : " + request.args.line)
        
        // This returns the list of action names before arguments. e.g. ["manage", "movies", "createSample"]
        println("parts  : " + request.parts)
        println("path   : " + request.fullName)
        // This is useful if leveraging the 3 part routing system for Slate Kit APIs
        println("area   : " + request.area)
        println("api    : " + request.name)
        println("action : " + request.action)
        
        // Access the arguments
        println("arg #  : " + request.args.size())
        println("arg 1  : " + request.args.getString("title"))
        // ...
    }To execute the command, you can override the executeRequest method
    /**
     * Handle execution of the CLI Request
     */
    override suspend fun executeRequest(request: CliRequest): Try<CliResponse<*>> {
        
        // Access the arguments
        val title = request.args.getString("title"))
        val date  = request.args.getLocalDate("date"))
        // Process... 
        // Return
        return Success(
                CliResponse(
                        request = request,
                        success = true,
                        code = Codes.SUCCESS.code,
                        meta = mapOf(),
                        value = "Sample Response",
                        msg = "Processed",
                        err = null,
                        tag = "tag-123"
                ))
    }You must return a CliResponse upon execution. This leverages the Slate Kit Result
     
    return Success(
                CliResponse(
                        request = request,
                        success = true,
                        code = Codes.SUCCESS.code,
                        meta = mapOf(),
                        value = "Sample Response",
                        msg = "Processed",
                        err = null,
                        tag = "tag-123"
                ))You can have commands run during the start up of the CLI. This is accomplished by supplying a list of String text commands to the CLI during construction in the commands parameter.
    open class CLI(
        val settings: CliSettings,
        val info: Info,
        val folders: Folders?,
        val callback: ((CLI, CliRequest) -> CliResponse<*>)? = null,
        commands: List<String?>? = listOf(),
        ioReader: ((Unit) -> String?)? = null,
        ioWriter: ((CliOutput) -> Unit)? = null,
        val serializer:(Any?, ContentType) -> Content
    )The most important and powerful feature of the CLI is integration with Slate Kit APIs. Refer to Sample for more info.
    // 1. The API keys( DocApi, SetupApi are authenticated using an sample API key )
    val keys = listOf(ApiKey( name ="cli", key = "abc", roles = "dev,qa,ops,admin"))
    // 2. Authentication
    val auth = Authenticator(keys)
    // 3. Load all the Slate Kit Universal APIs
    val apis = listOf(
            slatekit.apis.core.Api(
                klass = SampleApi::class, 
                singleton = SampleApi(ctx)
            )
    )
    // 4. Makes the APIs accessible on the CLI runner
    val cli = CliApi(
            ctx = ctx,
            auth = auth,
            settings = CliSettings(enableLogging = true, enableOutput = true),
            apiItems = apis,
            metaTransform = {
                listOf("api-key" to keys.first().key)
            },
            serializer = {item, type -> Content.csv(slatekit.meta.Serialization.csv().serialize(item))}
    )
    // 5. Run interactive mode
    return cli.run()