use crate::server::app::AppState;
use crate::server::errors::{error, method_not_allowed};
use crate::server::sse;
use axum::body::Bytes;
use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::routing::{get, post};
use axum::{Json, Router};
use serde_json::json;
pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route(
"/api/services/:name/test",
post(start).fallback(method_not_allowed),
)
.route(
"/api/services/:name/test/stream",
get(watch).fallback(method_not_allowed),
)
}
async fn start(State(state): State<AppState>, Path(name): Path<String>, body: Bytes) -> Response {
let pattern = crate::server::body::parse_form(&body)
.get("pattern")
.cloned();
let config = match state.config_store.load().await {
Ok(config) => config,
Err(reason) => return error(StatusCode::CONFLICT, &reason.to_string()),
};
let cwd = crate::server::routes::daemon_cwd();
match state
.tests
.run(&config, &cwd, &name, pattern.as_deref())
.await
{
Ok(run) => Json(json!({ "ok": true, "run": run })).into_response(),
Err(reason) => error(StatusCode::CONFLICT, &reason),
}
}
async fn watch(State(state): State<AppState>, Path(name): Path<String>) -> Response {
let replay = state
.tests
.current(&name)
.map(|run| {
sse::named(
"status",
nomoreide_core::test_runner::TestRunEvent {
kind: "status".to_string(),
run,
line: None,
},
)
})
.into_iter()
.collect();
let wanted = name.clone();
sse::stream(
sse::RETRY_AND_PING,
replay,
state.tests.events(),
move |event| (event.run.service == wanted).then(|| sse::named(&event.kind.clone(), event)),
)
}