use serde::Deserialize;
use super::SourceAdapter;
use crate::model::{Match, Query, Source};
use crate::Result;
const DEFAULT_BASE_URL: &str = "https://search.maven.org";
#[derive(Debug, Clone)]
pub struct Maven {
client: reqwest::Client,
base_url: String,
}
impl Maven {
pub fn new(client: reqwest::Client) -> Self {
Self::with_base_url(client, DEFAULT_BASE_URL.to_string())
}
pub fn with_base_url(client: reqwest::Client, base_url: String) -> Self {
Self { client, base_url }
}
}
#[derive(Debug, Deserialize)]
struct SolrResponse {
response: SolrDocs,
}
#[derive(Debug, Deserialize)]
struct SolrDocs {
docs: Vec<SolrDoc>,
}
#[derive(Debug, Deserialize)]
struct SolrDoc {
#[serde(default)]
g: String,
#[serde(default)]
a: String,
#[serde(default, rename = "versionCount")]
version_count: Option<u64>,
}
#[async_trait::async_trait]
impl SourceAdapter for Maven {
fn id(&self) -> Source {
Source::Maven
}
async fn search(&self, query: &Query) -> Result<Vec<Match>> {
let url = format!("{}/solrsearch/select", self.base_url);
let q = query.keywords.join(" ");
let body: SolrResponse = self
.client
.get(&url)
.query(&[("q", q.as_str()), ("rows", "20"), ("wt", "json")])
.send()
.await?
.error_for_status()?
.json()
.await?;
Ok(body
.response
.docs
.into_iter()
.map(|d| {
let name = format!("{}:{}", d.g, d.a);
let url = format!("https://central.sonatype.com/artifact/{}/{}", d.g, d.a);
Match {
description: d.g.clone(),
name,
source: Source::Maven,
url,
popularity: d.version_count,
similarity: 0.0,
}
})
.collect())
}
}