diff --git a/Cargo.lock b/Cargo.lock index f3b39531..f248277d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1052,6 +1052,7 @@ dependencies = [ "anyhow", "clap", "edgee-api-client", + "edgee-components-runtime", "edgee-server", "inquire", "miette", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 30fb8677..c4a5af8a 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -24,6 +24,7 @@ tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } edgee-api-client.workspace = true edgee-server.workspace = true +edgee-components-runtime.workspace = true [features] bundled = [ diff --git a/crates/cli/src/commands/components/check.rs b/crates/cli/src/commands/components/check.rs new file mode 100644 index 00000000..766e119e --- /dev/null +++ b/crates/cli/src/commands/components/check.rs @@ -0,0 +1,87 @@ +use edgee_components_runtime::config::{ + ComponentsConfiguration, ConsentMappingComponents, DataCollectionComponents, +}; +use edgee_components_runtime::context::ComponentsContext; + +#[derive(Debug, clap::Parser)] +pub struct Options {} + +enum ComponentType { + DataCollection, + #[allow(dead_code)] + ConsentMapping, +} + +async fn check_component( + component_type: ComponentType, + component_path: &str, +) -> anyhow::Result<()> { + if !std::path::Path::new(component_path).exists() { + return Err(anyhow::anyhow!( + "Component {} does not exist. Please run `edgee component build` first", + component_path + )); + } + + let config = match component_type { + ComponentType::DataCollection => ComponentsConfiguration { + data_collection: vec![DataCollectionComponents { + id: component_path.to_string(), + file: component_path.to_string(), + ..Default::default() + }], + ..Default::default() + }, + ComponentType::ConsentMapping => ComponentsConfiguration { + consent_mapping: vec![ConsentMappingComponents { + name: component_path.to_string(), + component: component_path.to_string(), + ..Default::default() + }], + ..Default::default() + }, + }; + + let context = ComponentsContext::new(&config) + .map_err(|e| anyhow::anyhow!("Invalid component {}: {}", component_path, e))?; + + let mut store = context.empty_store(); + + match component_type { + ComponentType::DataCollection => { + let _ = context + .get_data_collection_instance(component_path, &mut store) + .await?; + } + ComponentType::ConsentMapping => { + let _ = context + .get_consent_mapping_instance(component_path, &mut store) + .await?; + } + } + + println!("Component {} is valid", component_path); + Ok(()) +} + +pub async fn run(_opts: Options) -> anyhow::Result<()> { + use crate::components::manifest::{self, Manifest}; + + let manifest_path = manifest::find_manifest_path().ok_or_else(|| { + anyhow::anyhow!("Edgee Manifest not found. Please run `edgee component create` and start from a template or `edgee component init` to create a new empty manifest in this folder.") + })?; + + let manifest = Manifest::load(&manifest_path)?; + let component_path = manifest + .package + .build + .output_path + .into_os_string() + .into_string() + .map_err(|_| anyhow::anyhow!("No output path found in manifest."))?; + + // TODO: dont assume that it is a data collection component, add type in manifest + check_component(ComponentType::DataCollection, &component_path).await?; + + Ok(()) +} diff --git a/crates/cli/src/commands/components/mod.rs b/crates/cli/src/commands/components/mod.rs index dca3537d..2fc67e3f 100644 --- a/crates/cli/src/commands/components/mod.rs +++ b/crates/cli/src/commands/components/mod.rs @@ -13,6 +13,8 @@ setup_commands! { Push(push), /// List currently pulled components List(list), + /// Check if a component implements the required interfaces + Check(check) } pub type Options = Command;