use {
crate::{
commands::{types::*, utils},
types::Error,
},
argh::{ArgsInfo, FromArgs},
async_trait::async_trait,
diagnostics_data::{Inspect, InspectData},
diagnostics_hierarchy::DiagnosticsHierarchy,
serde::Serialize,
std::fmt,
};
#[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "selectors")]
pub struct SelectorsCommand {
#[argh(option)]
pub manifest: Option<String>,
#[argh(positional)]
pub selectors: Vec<String>,
#[argh(option)]
pub accessor: Option<String>,
}
#[async_trait]
impl Command for SelectorsCommand {
type Result = SelectorsResult;
async fn execute<P: DiagnosticsProvider>(&self, provider: &P) -> Result<Self::Result, Error> {
if self.selectors.is_empty() && self.manifest.is_none() {
return Err(Error::invalid_arguments("Expected 1 or more selectors. Got zero."));
}
let selectors = utils::get_selectors_for_manifest(
&self.manifest,
&self.selectors,
&self.accessor,
provider,
)
.await?;
let selectors = utils::expand_selectors(selectors)?;
let mut results = provider.snapshot::<Inspect>(&self.accessor, &selectors).await?;
for result in results.iter_mut() {
if let Some(hierarchy) = &mut result.payload {
hierarchy.sort();
}
}
Ok(SelectorsResult(inspect_to_selectors(results)))
}
}
#[derive(Serialize)]
pub struct SelectorsResult(Vec<String>);
impl fmt::Display for SelectorsResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for item in self.0.iter() {
writeln!(f, "{}", item)?;
}
Ok(())
}
}
fn get_selectors(moniker: String, hierarchy: DiagnosticsHierarchy) -> Vec<String> {
let component_selector = selectors::sanitize_moniker_for_selectors(&moniker);
hierarchy
.property_iter()
.flat_map(|(node_path, maybe_property)| maybe_property.map(|prop| (node_path, prop)))
.map(|(node_path, property)| {
let node_selector = node_path
.iter()
.map(|s| selectors::sanitize_string_for_selectors(s))
.collect::<Vec<_>>()
.join("/");
let property_selector = selectors::sanitize_string_for_selectors(property.name());
format!("{}:{}:{}", component_selector, node_selector, property_selector)
})
.collect()
}
fn inspect_to_selectors(inspect_data: Vec<InspectData>) -> Vec<String> {
let mut result = inspect_data
.into_iter()
.filter_map(|schema| {
let moniker = schema.moniker;
schema.payload.map(|hierarchy| get_selectors(moniker, hierarchy))
})
.flat_map(|results| results)
.collect::<Vec<_>>();
result.sort();
result
}