mod executor;
mod parser;
pub use executor::*;
pub use parser::*;
use axum::{extract::State, routing::post, Json, Router};
use serde::{Deserialize, Serialize};
use crate::error::Result;
use crate::state::AppState;
pub fn router() -> Router<AppState> {
Router::new()
.route("/sparql", post(execute_sparql))
.route("/api/v1/sparql", post(execute_sparql))
}
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "mcp", derive(schemars::JsonSchema))]
pub struct SparqlRequest {
pub query: String,
pub default_graph: Option<String>,
pub named_graphs: Option<Vec<String>>,
}
#[derive(Debug, Serialize)]
pub struct SparqlResponse {
pub result_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub variables: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bindings: Option<Vec<serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub boolean: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub triple_count: Option<usize>,
pub execution_time_ms: u64,
}
pub async fn execute_sparql(
State(state): State<AppState>,
Json(req): Json<SparqlRequest>,
) -> Result<Json<SparqlResponse>> {
let resp = crate::service::sparql::execute(&state, req).await?;
Ok(Json(resp))
}
#[derive(Debug)]
pub struct SparqlResult {
pub result_type: String,
pub variables: Option<Vec<String>>,
pub bindings: Option<Vec<serde_json::Value>>,
pub boolean: Option<bool>,
pub triple_count: Option<usize>,
}