rivox 1.0.0

Universal polyglot build coordination layer for Python, Rust, and Node monorepos
Documentation
use super::{EdgeType, GraphEdge, GraphNode};
use crate::config::manifest::RivoxManifest;
use anyhow::Result;
use petgraph::graph::{DiGraph, NodeIndex};
use std::collections::HashMap;

pub struct UnifiedGraph {
    pub graph: DiGraph<GraphNode, GraphEdge>,
    pub node_map: HashMap<String, NodeIndex>,
}

impl UnifiedGraph {
    pub fn new() -> Self {
        Self {
            graph: DiGraph::new(),
            node_map: HashMap::new(),
        }
    }
}

impl Default for UnifiedGraph {
    fn default() -> Self {
        Self::new()
    }
}

impl UnifiedGraph {
    pub fn add_nodes(&mut self, nodes: Vec<GraphNode>) {
        for node in nodes {
            let key = format!(
                "{}:{}:{}",
                node.ecosystem, node.package_name, node.resolved_version
            );
            if !self.node_map.contains_key(&key) {
                let idx = self.graph.add_node(node);
                self.node_map.insert(key, idx);
            }
        }
    }

    pub fn apply_cross_refs(&mut self, manifest: &RivoxManifest) -> Result<()> {
        for cr in &manifest.cross_refs {
            let from_key = &cr.consumer;
            let to_key = &cr.dependency;

            // Look up matching nodes or create virtual boundary dependency edges
            if let (Some(&from_idx), Some(&to_idx)) =
                (self.node_map.get(from_key), self.node_map.get(to_key))
            {
                let edge = GraphEdge {
                    from_node: from_key.clone(),
                    to_node: to_key.clone(),
                    edge_type: EdgeType::UserDeclaredCrossRef,
                };
                self.graph.add_edge(from_idx, to_idx, edge);
            }
        }
        Ok(())
    }
}