use anyhow::{Context, Result};
use serde::Serialize;
const GNOMAD_API_URL: &str = "https://gnomad.broadinstitute.org/api";
pub struct GnomadClient {
client: reqwest::Client,
}
#[derive(Debug, Serialize)]
pub struct GnomadVariant {
pub rsid: Option<String>,
pub chrom: String,
pub pos: u64,
pub r#ref: String,
pub alt: String,
pub af: Option<f64>,
pub populations: Vec<PopulationFrequency>,
pub homozygote_count: Option<u64>,
pub allele_count: Option<u64>,
pub allele_number: Option<u64>,
}
#[derive(Debug, Serialize)]
pub struct PopulationFrequency {
pub population: String,
pub af: f64,
pub ac: u64,
pub an: u64,
}
impl GnomadClient {
pub fn new() -> Self {
Self {
client: reqwest::Client::new(),
}
}
pub async fn query(&self, query: &str) -> Result<serde_json::Value> {
let graphql_query = if query.starts_with("rs") {
format!(
r#"{{
variant(rsid: "{query}", dataset: gnomad_r4) {{
rsids
chrom
pos
ref
alt
exome {{
ac
an
ac_hom
populations {{
id
ac
an
}}
}}
genome {{
ac
an
ac_hom
populations {{
id
ac
an
}}
}}
}}
}}"#,
)
} else {
let variant_id = query.replace(':', "-");
format!(
r#"{{
variant(variantId: "{variant_id}", dataset: gnomad_r4) {{
rsids
chrom
pos
ref
alt
exome {{
ac
an
ac_hom
populations {{
id
ac
an
}}
}}
genome {{
ac
an
ac_hom
populations {{
id
ac
an
}}
}}
}}
}}"#,
)
};
let response = self
.client
.post(GNOMAD_API_URL)
.json(&serde_json::json!({ "query": graphql_query }))
.send()
.await
.context("Failed to reach gnomAD API")?;
if !response.status().is_success() {
let status = response.status();
let body = response.text().await.unwrap_or_default();
anyhow::bail!("gnomAD API returned {status}: {body}");
}
let data: serde_json::Value = response
.json()
.await
.context("Failed to parse gnomAD response")?;
Ok(data)
}
}