mod handlers;
mod screenshot;
mod types;
pub use types::{
EvalCommand, EvalRequest, EvalResponse, QueryRequest, ResizeRequest, ResizeResponse,
StatusResponse,
};
use axum::{routing::get, Router};
use std::sync::Arc;
use tokio::sync::mpsc;
pub struct BridgeState {
pub app_name: String,
pub eval_tx: mpsc::Sender<EvalCommand>,
pub started_at: std::time::Instant,
pub pid: u32,
}
#[cfg(not(tarpaulin_include))]
pub fn start_bridge(port: u16, app_name: impl Into<String>) -> mpsc::Receiver<EvalCommand> {
let (eval_tx, eval_rx) = mpsc::channel::<EvalCommand>(32);
let state = Arc::new(BridgeState {
app_name: app_name.into(),
eval_tx,
started_at: std::time::Instant::now(),
pid: std::process::id(),
});
let app = Router::new()
.route("/status", get(handlers::status))
.route("/eval", axum::routing::post(handlers::eval))
.route("/query", axum::routing::post(handlers::query))
.route("/dom", get(handlers::dom))
.route("/inspect", axum::routing::post(handlers::inspect))
.route(
"/validate-classes",
axum::routing::post(handlers::validate_classes),
)
.route("/diagnose", get(handlers::diagnose))
.route("/screenshot", axum::routing::post(handlers::screenshot))
.route("/resize", axum::routing::post(handlers::resize))
.with_state(state);
tokio::spawn(async move {
let addr = format!("127.0.0.1:{}", port);
let listener = match tokio::net::TcpListener::bind(&addr).await {
Ok(l) => l,
Err(e) => {
tracing::error!("Failed to bind inspector bridge on {}: {}", addr, e);
return;
}
};
tracing::info!("Inspector bridge listening on http://{}", addr);
let _ = axum::serve(listener, app).await;
});
eval_rx
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bridge_state_creation() {
let (tx, _rx) = mpsc::channel(1);
let state = BridgeState {
app_name: "test".to_string(),
eval_tx: tx,
started_at: std::time::Instant::now(),
pid: 12345,
};
assert_eq!(state.app_name, "test");
assert_eq!(state.pid, 12345);
}
}