use crate::models::{CacheType, DatabaseType, SearchType, ServiceRole, ServiceType};
pub struct ServiceSignature {
pub port: u16,
pub process_pattern: &'static str,
pub service_type: ServiceType,
pub name: &'static str,
pub systemd_unit: Option<&'static str>,
pub role: ServiceRole,
}
pub struct ServiceSignatures;
impl ServiceSignatures {
pub fn all() -> Vec<ServiceSignature> {
vec![
ServiceSignature {
port: 5432,
process_pattern: "postgres",
service_type: ServiceType::Database { database: DatabaseType::Postgres },
name: "PostgreSQL",
systemd_unit: Some("postgresql.service"),
role: ServiceRole::Database,
},
ServiceSignature {
port: 3306,
process_pattern: "mysqld",
service_type: ServiceType::Database { database: DatabaseType::MySQL },
name: "MySQL",
systemd_unit: Some("mysql.service"),
role: ServiceRole::Database,
},
ServiceSignature {
port: 27017,
process_pattern: "mongod",
service_type: ServiceType::Database { database: DatabaseType::MongoDB },
name: "MongoDB",
systemd_unit: Some("mongod.service"),
role: ServiceRole::Database,
},
ServiceSignature {
port: 6379,
process_pattern: "redis-server",
service_type: ServiceType::Cache { cache: CacheType::Redis },
name: "Redis",
systemd_unit: Some("redis-server.service"),
role: ServiceRole::Cache,
},
ServiceSignature {
port: 11211,
process_pattern: "memcached",
service_type: ServiceType::Cache { cache: CacheType::Memcached },
name: "Memcached",
systemd_unit: Some("memcached.service"),
role: ServiceRole::Cache,
},
ServiceSignature {
port: 9200,
process_pattern: "elasticsearch",
service_type: ServiceType::Search { search: SearchType::Elasticsearch },
name: "Elasticsearch",
systemd_unit: Some("elasticsearch.service"),
role: ServiceRole::Unknown, },
ServiceSignature {
port: 7700,
process_pattern: "meilisearch",
service_type: ServiceType::Search { search: SearchType::Meilisearch },
name: "Meilisearch",
systemd_unit: Some("meilisearch.service"),
role: ServiceRole::Unknown,
},
ServiceSignature {
port: 3000,
process_pattern: "node",
service_type: ServiceType::HttpServer,
name: "Node.js Dev Server",
systemd_unit: None,
role: ServiceRole::Frontend, },
ServiceSignature {
port: 4200,
process_pattern: "node",
service_type: ServiceType::HttpServer,
name: "Angular Dev Server",
systemd_unit: None,
role: ServiceRole::Frontend,
},
ServiceSignature {
port: 5173,
process_pattern: "node",
service_type: ServiceType::HttpServer,
name: "Vite Dev Server",
systemd_unit: None,
role: ServiceRole::Frontend,
},
ServiceSignature {
port: 8000,
process_pattern: "python",
service_type: ServiceType::HttpServer,
name: "Python Dev Server",
systemd_unit: None,
role: ServiceRole::Backend,
},
ServiceSignature {
port: 8080,
process_pattern: "java",
service_type: ServiceType::HttpServer,
name: "Java Server",
systemd_unit: None,
role: ServiceRole::Backend,
},
]
}
pub fn find_by_port(port: u16) -> Option<ServiceSignature> {
Self::all().into_iter().find(|sig| sig.port == port)
}
pub fn find_by_process(process_name: &str) -> Option<ServiceSignature> {
Self::all()
.into_iter()
.find(|sig| process_name.contains(sig.process_pattern))
}
pub fn infer_role(port: u16, process_name: Option<&str>, service_type: &ServiceType) -> ServiceRole {
if let Some(sig) = Self::find_by_port(port) {
return sig.role;
}
if let Some(process_name) = process_name {
if let Some(sig) = Self::find_by_process(process_name) {
return sig.role;
}
let process_lower = process_name.to_lowercase();
if process_lower.contains("vite") || process_lower.contains("webpack")
|| process_lower.contains("next") || process_lower.contains("react")
|| process_lower.contains("angular") || process_lower.contains("vue") {
return ServiceRole::Frontend;
}
if process_lower.contains("python") || process_lower.contains("java")
|| process_lower.contains("go") || process_lower.contains("rust")
|| process_lower.contains("node") && !process_lower.contains("vite")
&& !process_lower.contains("webpack") && !process_lower.contains("next") {
return ServiceRole::Backend;
}
}
if (3000..=4000).contains(&port) || port == 5173 || port == 4200 {
return ServiceRole::Frontend;
}
if (8000..=9000).contains(&port) || port == 5000 {
return ServiceRole::Backend;
}
match service_type {
ServiceType::Database { .. } => ServiceRole::Database,
ServiceType::Cache { .. } => ServiceRole::Cache,
_ => ServiceRole::Unknown,
}
}
}