feat(cups): add HTTP client for cups API

- Add CupsClient with create, list, get, update, delete methods
- Register cups() accessor on BrewlogClient
This commit is contained in:
Jon Seager 2026-02-03 16:36:14 +00:00
parent 928c4c9aea
commit c2e9c7395c
No known key found for this signature in database
2 changed files with 87 additions and 0 deletions

View file

@ -0,0 +1,82 @@
use anyhow::{Context, Result};
use reqwest::StatusCode;
use crate::domain::cups::{Cup, CupWithDetails, NewCup, UpdateCup};
use crate::domain::ids::CupId;
use super::BrewlogClient;
pub struct CupsClient<'a> {
inner: &'a BrewlogClient,
}
impl<'a> CupsClient<'a> {
pub(crate) fn new(inner: &'a BrewlogClient) -> Self {
Self { inner }
}
pub async fn create(&self, payload: &NewCup) -> Result<Cup> {
let url = self.inner.endpoint("api/v1/cups")?;
let response = self
.inner
.request(reqwest::Method::POST, url)
.json(payload)
.send()
.await
.context("failed to issue create cup request")?;
self.inner.handle_response(response).await
}
pub async fn list(&self) -> Result<Vec<CupWithDetails>> {
let url = self.inner.endpoint("api/v1/cups")?;
let response = self
.inner
.request(reqwest::Method::GET, url)
.send()
.await
.context("failed to issue list cups request")?;
self.inner.handle_response(response).await
}
pub async fn get(&self, id: CupId) -> Result<CupWithDetails> {
let url = self.inner.endpoint(&format!("api/v1/cups/{id}"))?;
let response = self
.inner
.request(reqwest::Method::GET, url)
.send()
.await
.context("failed to issue get cup request")?;
self.inner.handle_response(response).await
}
pub async fn update(&self, id: CupId, payload: &UpdateCup) -> Result<Cup> {
let url = self.inner.endpoint(&format!("api/v1/cups/{id}"))?;
let response = self
.inner
.request(reqwest::Method::PUT, url)
.json(payload)
.send()
.await
.context("failed to issue update cup request")?;
self.inner.handle_response(response).await
}
pub async fn delete(&self, id: CupId) -> Result<()> {
let url = self.inner.endpoint(&format!("api/v1/cups/{id}"))?;
let response = self
.inner
.request(reqwest::Method::DELETE, url)
.send()
.await
.context("failed to issue delete cup request")?;
match response.status() {
StatusCode::NO_CONTENT => Ok(()),
_ => Err(self.inner.response_error(response).await),
}
}
}

View file

@ -1,6 +1,7 @@
pub mod bags; pub mod bags;
pub mod brews; pub mod brews;
pub mod cafes; pub mod cafes;
pub mod cups;
pub mod gear; pub mod gear;
pub mod roasters; pub mod roasters;
pub mod roasts; pub mod roasts;
@ -71,6 +72,10 @@ impl BrewlogClient {
cafes::CafesClient::new(self) cafes::CafesClient::new(self)
} }
pub fn cups(&self) -> cups::CupsClient<'_> {
cups::CupsClient::new(self)
}
pub(crate) fn endpoint(&self, path: &str) -> Result<Url> { pub(crate) fn endpoint(&self, path: &str) -> Result<Url> {
self.base_url self.base_url
.join(path) .join(path)