Skip to main content

Module command

Module command 

Source
Expand description

The app’s own commands, run like the built-in ones: my-app admin:create --email a@b.c (or rnx admin:create … during development).

use renox::command::Args;

async fn create_admin(args: Args, state: AppState) -> Result {
    let (Some(email), Some(password)) = (args.value("--email"), args.value("--password")) else {
        return Err(Error::BadRequest("usage: admin:create --email E --password P".into()));
    };
    User::register(&state.db, "Admin", email, password).await?;
    println!("Created {email}.");
    Ok(())
}

App::new().command("admin:create", "Create an admin user (--email, --password)", create_admin)

Commands run after the app boots (the database is connected, migrations are not run for you) and appear in my-app help.

A typed command declares its arguments with clap, so they’re parsed and checked for you, and my-app catalog:import --help prints its usage:

use renox::clap;
use renox::command::AppCommand;

/// Import products from a CSV file.
#[derive(clap::Parser)]
#[command(name = "catalog:import")]
struct ImportCatalog {
    /// The CSV file.
    file: std::path::PathBuf,
    /// Show what would change without saving.
    #[arg(long)]
    dry_run: bool,
    #[arg(long, default_value_t = 500)]
    batch: usize,
}

impl AppCommand for ImportCatalog {
    async fn run(self, state: AppState) -> Result {
        println!("importing {} ({} a batch)", self.file.display(), self.batch);
        Ok(())
    }
}

App::new().typed_command::<ImportCatalog>()

Ask for what’s missing with crate::prompt.

Structs§

Args
The words after the command’s name.

Traits§

AppCommand
A command whose arguments are a clap Parser: its #[command(name = …)] is the command’s name, and its doc comment (or about) the line in my-app help. Register it with App::typed_command.