#![warn(missing_docs)]
#![warn(unused_extern_crates)]
#![warn(unused_imports)]
use clap::{CommandFactory, FromArgMatches, Parser};
use log::warn;
use pezsc_service::Configuration;
pub mod arg_enums;
pub mod commands;
mod config;
mod error;
mod params;
mod runner;
mod signals;
pub use arg_enums::*;
pub use clap;
pub use commands::*;
pub use config::*;
pub use error::*;
pub use params::*;
pub use pezsc_service::{ChainSpec, Role};
pub use pezsc_tracing::logging::LoggerBuilder;
pub use pezsp_version::RuntimeVersion;
pub use runner::*;
pub use signals::Signals;
pub trait BizinikiwiCli: Sized {
fn impl_name() -> String;
fn impl_version() -> String;
fn executable_name() -> String {
std::env::current_exe()
.ok()
.and_then(|e| e.file_name().map(|s| s.to_os_string()))
.and_then(|w| w.into_string().ok())
.unwrap_or_else(|| env!("CARGO_PKG_NAME").into())
}
fn description() -> String;
fn author() -> String;
fn support_url() -> String;
fn copyright_start_year() -> i32;
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn ChainSpec>, String>;
fn from_args() -> Self
where
Self: Parser + Sized,
{
<Self as BizinikiwiCli>::from_iter(&mut std::env::args_os())
}
fn from_iter<I>(iter: I) -> Self
where
Self: Parser + Sized,
I: IntoIterator,
I::Item: Into<std::ffi::OsString> + Clone,
{
let app = <Self as CommandFactory>::command();
let app = Self::setup_command(app);
let matches = app.try_get_matches_from(iter).unwrap_or_else(|e| e.exit());
<Self as FromArgMatches>::from_arg_matches(&matches).unwrap_or_else(|e| e.exit())
}
fn try_from_iter<I>(iter: I) -> clap::error::Result<Self>
where
Self: Parser + Sized,
I: IntoIterator,
I::Item: Into<std::ffi::OsString> + Clone,
{
let app = <Self as CommandFactory>::command();
let app = Self::setup_command(app);
let matches = app.try_get_matches_from(iter)?;
<Self as FromArgMatches>::from_arg_matches(&matches)
}
fn client_id() -> String {
format!("{}/v{}", Self::impl_name(), Self::impl_version())
}
fn create_configuration<T: CliConfiguration<DVC>, DVC: DefaultConfigurationValues>(
&self,
command: &T,
tokio_handle: tokio::runtime::Handle,
) -> error::Result<Configuration> {
command.create_configuration(self, tokio_handle)
}
fn create_runner<T: CliConfiguration<DVC>, DVC: DefaultConfigurationValues>(
&self,
command: &T,
) -> Result<Runner<Self>> {
self.create_runner_with_logger_hook(command, |_, _| {})
}
fn create_runner_with_logger_hook<
T: CliConfiguration<DVC>,
DVC: DefaultConfigurationValues,
F,
>(
&self,
command: &T,
logger_hook: F,
) -> Result<Runner<Self>>
where
F: FnOnce(&mut LoggerBuilder, &Configuration),
{
let tokio_runtime = build_runtime()?;
let signals = tokio_runtime.block_on(async { Signals::capture() })?;
let config = command.create_configuration(self, tokio_runtime.handle().clone())?;
command.init(&Self::support_url(), &Self::impl_version(), |logger_builder| {
logger_hook(logger_builder, &config)
})?;
Runner::new(config, tokio_runtime, signals)
}
fn setup_command(mut cmd: clap::Command) -> clap::Command {
let mut full_version = Self::impl_version();
full_version.push('\n');
cmd = cmd
.name(Self::executable_name())
.version(full_version)
.author(Self::author())
.about(Self::description())
.long_about(Self::description())
.after_help(format!("Support: {}", Self::support_url()))
.propagate_version(true)
.args_conflicts_with_subcommands(true)
.subcommand_negates_reqs(true);
cmd
}
}