use serde::Deserialize;
use super::encode_path;
use super::BugzillaClient;
use crate::error::{BzrError, Result};
use crate::types::{CreateProductParams, Product, ProductListType, UpdateProductParams};
#[derive(Deserialize)]
struct ProductAccessibleResponse {
ids: Vec<u64>,
}
#[derive(Deserialize)]
struct ProductResponse {
products: Vec<Product>,
}
impl BugzillaClient {
pub async fn list_products_by_type(
&self,
product_type: ProductListType,
) -> Result<Vec<Product>> {
let endpoint = product_type.as_api_path();
let accessible: ProductAccessibleResponse = self.get_json(endpoint).await?;
if accessible.ids.is_empty() {
return Ok(Vec::new());
}
let mut all_products = Vec::new();
for chunk in accessible.ids.chunks(50) {
let id_params: Vec<(&str, String)> =
chunk.iter().map(|id| ("ids", id.to_string())).collect();
let req = self.apply_auth(self.http.get(self.url("product")).query(&id_params));
let resp = self.send(req).await?;
let data: ProductResponse = self.parse_json(resp).await?;
all_products.extend(data.products);
}
Ok(all_products)
}
pub async fn create_product(&self, params: &CreateProductParams) -> Result<u64> {
self.post_json_id("product", params).await
}
pub async fn update_product(&self, name: &str, updates: &UpdateProductParams) -> Result<()> {
self.put_json(&format!("product/{}", encode_path(name)), updates)
.await
}
pub async fn get_product(&self, name: &str) -> Result<Product> {
let data: ProductResponse = self.get_json_query("product", &[("names", name)]).await?;
data.products
.into_iter()
.next()
.ok_or_else(|| BzrError::NotFound {
resource: "product",
id: name.to_string(),
})
}
}
#[cfg(test)]
#[path = "product_tests.rs"]
mod tests;