use axum::{Json, extract::State, response::IntoResponse};
use fraiseql_core::db::traits::DatabaseAdapter;
use serde::Serialize;
use tracing::debug;
use crate::routes::graphql::AppState;
#[derive(Debug, Serialize)]
pub struct IntrospectionResponse {
pub types: Vec<TypeInfo>,
pub queries: Vec<QueryInfo>,
pub mutations: Vec<MutationInfo>,
}
#[derive(Debug, Serialize)]
pub struct TypeInfo {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub field_count: usize,
}
#[derive(Debug, Serialize)]
pub struct QueryInfo {
pub name: String,
pub return_type: String,
pub returns_list: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
#[derive(Debug, Serialize)]
pub struct MutationInfo {
pub name: String,
pub return_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
pub async fn introspection_handler<A: DatabaseAdapter + Clone + Send + Sync + 'static>(
State(state): State<AppState<A>>,
) -> impl IntoResponse {
debug!("Introspection requested");
let schema = state.executor.schema();
let types: Vec<TypeInfo> = schema
.types
.iter()
.map(|t| TypeInfo {
name: t.name.clone(),
description: t.description.clone(),
field_count: t.fields.len(),
})
.collect();
let queries: Vec<QueryInfo> = schema
.queries
.iter()
.map(|q| QueryInfo {
name: q.name.clone(),
return_type: q.return_type.clone(),
returns_list: q.returns_list,
description: q.description.clone(),
})
.collect();
let mutations: Vec<MutationInfo> = schema
.mutations
.iter()
.map(|m| MutationInfo {
name: m.name.clone(),
return_type: m.return_type.clone(),
description: m.description.clone(),
})
.collect();
Json(IntrospectionResponse {
types,
queries,
mutations,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_type_info_serialization() {
let type_info = TypeInfo {
name: "User".to_string(),
description: Some("A user in the system".to_string()),
field_count: 3,
};
let json = serde_json::to_string(&type_info).unwrap();
assert!(json.contains("User"));
assert!(json.contains("field_count"));
}
}