mockforge_ui/
lib.rs

1//! # MockForge UI
2//!
3//! Web-based admin interface for managing mock servers.
4
5pub mod audit;
6pub mod auth;
7pub mod handlers;
8pub mod rbac;
9pub mod routes;
10// Templates module removed; static assets in `static/` are the single source of truth
11pub mod models;
12pub mod prometheus_client;
13pub mod time_travel_handlers;
14
15pub use models::{RequestLog, RouteInfo, ServerStatus, SystemInfo};
16pub use routes::create_admin_router;
17
18use std::net::SocketAddr;
19
20/// Start the admin UI server
21///
22/// # Arguments
23/// * `addr` - Address to bind the admin server to
24/// * `http_server_addr` - HTTP server address
25/// * `ws_server_addr` - WebSocket server address
26/// * `grpc_server_addr` - gRPC server address
27/// * `graphql_server_addr` - GraphQL server address
28/// * `api_enabled` - Whether API endpoints are enabled
29/// * `prometheus_url` - Prometheus metrics URL
30/// * `chaos_api_state` - Optional chaos API state for hot-reload support
31/// * `latency_injector` - Optional latency injector for hot-reload support
32/// * `mockai` - Optional MockAI instance for hot-reload support
33/// * `continuum_config` - Optional Reality Continuum configuration
34/// * `virtual_clock` - Optional virtual clock for time-based progression
35pub async fn start_admin_server(
36    addr: SocketAddr,
37    http_server_addr: Option<SocketAddr>,
38    ws_server_addr: Option<SocketAddr>,
39    grpc_server_addr: Option<SocketAddr>,
40    graphql_server_addr: Option<SocketAddr>,
41    api_enabled: bool,
42    prometheus_url: String,
43    chaos_api_state: Option<std::sync::Arc<mockforge_chaos::api::ChaosApiState>>,
44    latency_injector: Option<
45        std::sync::Arc<tokio::sync::RwLock<mockforge_core::latency::LatencyInjector>>,
46    >,
47    mockai: Option<
48        std::sync::Arc<tokio::sync::RwLock<mockforge_core::intelligent_behavior::MockAI>>,
49    >,
50    continuum_config: Option<mockforge_core::ContinuumConfig>,
51    virtual_clock: Option<std::sync::Arc<mockforge_core::VirtualClock>>,
52) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
53    let app = create_admin_router(
54        http_server_addr,
55        ws_server_addr,
56        grpc_server_addr,
57        graphql_server_addr,
58        api_enabled,
59        addr.port(),
60        prometheus_url,
61        chaos_api_state,
62        latency_injector,
63        mockai,
64        continuum_config,
65        virtual_clock,
66    );
67
68    tracing::info!("Starting MockForge Admin UI on {}", addr);
69
70    let listener = tokio::net::TcpListener::bind(addr).await.map_err(|e| {
71        format!(
72            "Failed to bind Admin UI server to port {}: {}\n\
73             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 {}",
74            addr.port(), e, addr.port(), addr.port()
75        )
76    })?;
77
78    axum::serve(listener, app).await?;
79
80    Ok(())
81}
82
83/// Get React UI HTML content
84pub fn get_admin_html() -> &'static str {
85    include_str!("../ui/dist/index.html")
86}
87
88/// Get React UI CSS content
89pub fn get_admin_css() -> &'static str {
90    include_str!("../ui/dist/assets/index.css")
91}
92
93/// Get React UI JavaScript content
94pub fn get_admin_js() -> &'static str {
95    include_str!("../ui/dist/assets/index.js")
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_get_admin_html() {
104        let html = get_admin_html();
105        assert!(!html.is_empty());
106        assert!(html.contains("<!DOCTYPE html>") || html.contains("<html"));
107    }
108
109    #[test]
110    fn test_get_admin_css() {
111        let css = get_admin_css();
112        assert!(!css.is_empty());
113    }
114
115    #[test]
116    fn test_get_admin_js() {
117        let js = get_admin_js();
118        assert!(!js.is_empty());
119    }
120}