use anyhow::Result;
use regex::Regex;
use crate::types::ProjectConfig;
use super::{RedisInfo, ServiceInfo, TopologyService};
impl TopologyService {
pub fn parse_redis_url(&self, url: &str) -> Result<RedisInfo> {
let url_pattern = Regex::new(r"redis://([^:]+):(\d+)")?;
if let Some(caps) = url_pattern.captures(url) {
let host = caps.get(1).map(|m| m.as_str()).unwrap_or("localhost");
let port = caps.get(2).and_then(|m| m.as_str().parse::<u16>().ok()).unwrap_or(6379);
Ok(RedisInfo {
url: url.to_string(),
host: host.to_string(),
port,
})
} else {
Ok(RedisInfo {
url: url.to_string(),
host: "localhost".to_string(),
port: 6379,
})
}
}
pub(super) fn extract_services(&self, config: &ProjectConfig) -> Vec<ServiceInfo> {
let mut services = Vec::new();
if let Some(http_api) = &config.services.http_api {
services.push(ServiceInfo {
name: "HTTP API".to_string(),
host: http_api.host.clone(),
port: http_api.port,
});
}
if let Some(db) = &config.services.database {
if let Some(port) = self.extract_port_from_url(&db.url) {
services.push(ServiceInfo {
name: "Database".to_string(),
host: self
.extract_host_from_url(&db.url)
.unwrap_or_else(|| "localhost".to_string()),
port,
});
}
}
services
}
fn extract_host_from_url(&self, url: &str) -> Option<String> {
let re = Regex::new(r"://([^:/@]+)").ok()?;
re.captures(url)
.and_then(|caps| caps.get(1).map(|m| m.as_str().to_string()))
}
fn extract_port_from_url(&self, url: &str) -> Option<u16> {
let re = Regex::new(r":(\d+)").ok()?;
re.captures(url)
.and_then(|caps| caps.get(1))
.and_then(|m| m.as_str().parse().ok())
}
}