greentic_flow/lint/
adapter_resolvable.rs1use crate::{ir::NodeKind, ir::classify_node_type, registry::AdapterCatalog};
2use greentic_types::Flow;
3
4#[derive(Clone, Debug, Default)]
5pub struct AdapterResolvableRule;
6
7impl AdapterResolvableRule {
8 pub fn check(flow: &Flow, catalog: &AdapterCatalog) -> Vec<String> {
9 let mut errors = Vec::new();
10 for (idx, (node_id, node)) in flow.nodes.iter().enumerate() {
11 let comp_str = if let Some(op) = &node.component.operation {
12 if node.component.id.as_str() == "component.exec" {
13 op.clone()
14 } else {
15 format!("{}.{}", node.component.id, op)
16 }
17 } else {
18 node.component.id.to_string()
19 };
20 match classify_node_type(&comp_str) {
21 NodeKind::Adapter {
22 namespace,
23 adapter,
24 operation,
25 } => {
26 if !catalog.contains(&namespace, &adapter, &operation) {
27 errors.push(format!(
28 "adapter_resolvable: node #{idx} ('{node_id}') component '{}' missing adapter '{}.{}' operation '{}'",
29 comp_str, namespace, adapter, operation
30 ));
31 }
32 }
33 NodeKind::Builtin(_) => {}
34 }
35 }
36 errors
37 }
38}