use crate::{Command, CommandGlobalOpts};
use async_trait::async_trait;
use miette::Result;
use ockam_node::Context;
use tracing::debug;
pub trait Resource<C: ParsedCommand>: Sized + Send + Sync + 'static {
const COMMAND_NAME: &'static str;
fn args(self) -> Vec<String> {
vec![]
}
}
#[async_trait]
pub trait ParsedCommand: Send + Sync + 'static {
async fn is_valid(&self, _ctx: &Context, _opts: &CommandGlobalOpts) -> Result<bool> {
Ok(true)
}
async fn run(&self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<()>;
}
#[async_trait]
impl<C> ParsedCommand for C
where
C: Command + Clone + Send + Sync + 'static,
{
async fn is_valid(&self, _ctx: &Context, _opts: &CommandGlobalOpts) -> Result<bool> {
Ok(true)
}
async fn run(&self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<()> {
debug!("running command {} {:?}", self.name(), self);
Ok(self.clone().run_with_retry(ctx, opts.clone()).await?)
}
}
pub struct ParsedCommands {
pub commands: Vec<Box<dyn ParsedCommand>>,
}
impl ParsedCommands {
pub fn new<C: ParsedCommand + Send + 'static>(commands: Vec<C>) -> Self {
ParsedCommands {
commands: commands
.into_iter()
.map(|c| {
let b: Box<dyn ParsedCommand> = Box::new(c);
b
})
.collect::<Vec<Box<dyn ParsedCommand>>>(),
}
}
pub async fn run(self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<()> {
let len = self.commands.len();
for (idx, cmd) in self.commands.into_iter().enumerate() {
if cmd.is_valid(ctx, opts).await? {
cmd.run(ctx, opts).await?;
if idx < len - 1 {
opts.terminal.write_line("")?;
}
}
}
Ok(())
}
}
impl<C: ParsedCommand> From<Vec<C>> for ParsedCommands {
fn from(cmds: Vec<C>) -> ParsedCommands {
ParsedCommands::new(cmds)
}
}