mecha10-dev 0.6.5

Mecha10 dev services — node discovery, topology analysis, and dev mode support
Documentation
//! Topology service for analyzing project structure
//!
//! This service provides static analysis of project topology including:
//! - Nodes and their enabled status
//! - Pub/sub topics (publishers and subscribers)
//! - Service ports (Redis, HTTP, database, etc.)

mod nodes;
mod ports;
mod source_scan;
mod topics;

use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

use crate::paths;
use crate::services::ConfigService;

/// Topology analysis result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Topology {
    pub project_name: String,
    pub redis: RedisInfo,
    pub nodes: Vec<NodeTopology>,
    pub topics: Vec<TopicTopology>,
}

/// Redis connection information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RedisInfo {
    pub url: String,
    pub host: String,
    pub port: u16,
}

/// Node topology information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeTopology {
    pub name: String,
    pub package: String,
    pub enabled: bool,
    pub description: Option<String>,
    pub publishes: Vec<TopicRef>,
    pub subscribes: Vec<TopicRef>,
}

/// Topic reference with message type
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct TopicRef {
    pub path: String,
    pub message_type: Option<String>,
}

/// Topic topology information (grouped by topic)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopicTopology {
    pub path: String,
    pub message_type: Option<String>,
    pub publishers: Vec<String>,
    pub subscribers: Vec<String>,
}

/// Topology service for static analysis
pub struct TopologyService {
    project_root: PathBuf,
}

impl TopologyService {
    /// Create a new topology service
    pub fn new(project_root: PathBuf) -> Self {
        Self { project_root }
    }

    /// Analyze project topology
    pub async fn analyze(&self) -> Result<Topology> {
        let config_path = self.project_root.join(paths::PROJECT_CONFIG);
        let config = ConfigService::load_from(&config_path).await?;

        let redis = self.parse_redis_url(&config.environments.redis_url())?;

        let nodes = self.analyze_nodes(&config).await?;

        let topics = self.build_topic_view(&nodes);

        Ok(Topology {
            project_name: config.name,
            redis,
            nodes,
            topics,
        })
    }
}