Command
Commands are a powerful way of extending you application or library beyond the web. Providing a way to run maintenance tasks from a console or trigger recurring jobs through an external "cron" runner.
Getting started
Creating a command handler
Getting started with a command is pretty easy. You simply have to create a new struct and implement the quokka::state::CommandHandler
trait.
The handler struct should implement the FromState trait too, so that it can be easily built by the global state.
use clap::Command;
use quokka::state::{CommandHandler, FromState};
#[derive(FromState)]
struct HelloWorldCommandHandler;
impl CommandHandler for HelloWorldCommandHandler {
fn args() -> clap::Command {
clap::Command::new("example:hello-world")
}
async fn call(self, _args: clap::ArgMatches) -> quokka::Result<()> {
println!("Hello World");
Ok(())
}
}
Register the command handler
With the handler created you simply have to add it within your bundle
struct HelloWorldBundle;
impl<S: Clone + Send + Sync + 'static> Pouch<S> for HelloWorldBundle {
fn configure_commands(&self, commands: &mut Commands<S>) -> quokka::Result<()> {
commands.register_command::<ListSessionsCommand>();
Ok(())
}
}
Create a CLI binary
Additionally you now have to initialize Quokka differently. Instead of calling the serve function you want to call the execute_command
function which will take care of collecting the commands and dispatching the commands from arguments. This requires either a second binary
or you have to wrap some parsing around it.
#[tokio::main]
async fn main() -> quokka::Result<()> {
quokka::Quokka::<DefaultState>::try_default()?
.load::<HelloWorldBundle>()?
.execute_command()
.await
}
A note on command names
The command name will be the name of the CLIs subcommand. It is recommanded to use the same bundle namespace as you would use for templates or other resources to prevent conflicts from happening.
And while it is possible to make a $BUNDE_NAME command and organize subcommands using clap, I'd like to recommend to use a subcommand per
task that should to be done. This reduces the complexity of your command handler and matching the proper subcommands and colling it with clap.