1pub mod handlers;
6pub mod routes;
7pub mod models;
9pub mod prometheus_client;
10pub mod time_travel_handlers;
11
12pub use models::{RequestLog, RouteInfo, ServerStatus, SystemInfo};
13pub use routes::create_admin_router;
14
15use std::net::SocketAddr;
16
17pub async fn start_admin_server(
19 addr: SocketAddr,
20 http_server_addr: Option<SocketAddr>,
21 ws_server_addr: Option<SocketAddr>,
22 grpc_server_addr: Option<SocketAddr>,
23 graphql_server_addr: Option<SocketAddr>,
24 api_enabled: bool,
25 prometheus_url: String,
26) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
27 let app = create_admin_router(
28 http_server_addr,
29 ws_server_addr,
30 grpc_server_addr,
31 graphql_server_addr,
32 api_enabled,
33 addr.port(),
34 prometheus_url,
35 );
36
37 tracing::info!("Starting MockForge Admin UI on {}", addr);
38
39 let listener = tokio::net::TcpListener::bind(addr).await.map_err(|e| {
40 format!(
41 "Failed to bind Admin UI server to port {}: {}\n\
42 Hint: The port may already be in use. Try using a different port with --admin-port or check if another process is using this port with: lsof -i :{} or netstat -tulpn | grep {}",
43 addr.port(), e, addr.port(), addr.port()
44 )
45 })?;
46
47 axum::serve(listener, app).await?;
48
49 Ok(())
50}
51
52pub fn get_admin_html() -> &'static str {
54 include_str!("../ui/dist/index.html")
55}
56
57pub fn get_admin_css() -> &'static str {
59 include_str!("../ui/dist/assets/index.css")
60}
61
62pub fn get_admin_js() -> &'static str {
64 include_str!("../ui/dist/assets/index.js")
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_get_admin_html() {
73 let html = get_admin_html();
74 assert!(!html.is_empty());
75 assert!(html.contains("<!DOCTYPE html>") || html.contains("<html"));
76 }
77
78 #[test]
79 fn test_get_admin_css() {
80 let css = get_admin_css();
81 assert!(!css.is_empty());
82 }
83
84 #[test]
85 fn test_get_admin_js() {
86 let js = get_admin_js();
87 assert!(!js.is_empty());
88 }
89}