feat(brews): add CLI commands

- Add brew add/list/get/delete subcommands
- Defaults: 15g coffee, 6.0 grind, 250ml water, 91°C temp
This commit is contained in:
Jon Seager 2026-02-02 19:31:14 +00:00
parent 6b7b7f9c6e
commit 35d64eaed2
No known key found for this signature in database
3 changed files with 103 additions and 1 deletions

View file

@ -2,7 +2,7 @@ use anyhow::Result;
use brewlog::application::{ServerConfig, serve}; use brewlog::application::{ServerConfig, serve};
use brewlog::infrastructure::client::BrewlogClient; use brewlog::infrastructure::client::BrewlogClient;
use brewlog::presentation::cli::{ use brewlog::presentation::cli::{
Cli, Commands, ServeCommand, bags, gear, roasters, roasts, tokens, Cli, Commands, ServeCommand, bags, brews, gear, roasters, roasts, tokens,
}; };
use clap::Parser; use clap::Parser;
@ -37,6 +37,10 @@ async fn main() -> Result<()> {
let client = BrewlogClient::from_base_url(&cli.api_url)?; let client = BrewlogClient::from_base_url(&cli.api_url)?;
gear::run(&client, command).await gear::run(&client, command).await
} }
Commands::Brew { command } => {
let client = BrewlogClient::from_base_url(&cli.api_url)?;
brews::run(&client, command).await
}
Commands::Token { command } => { Commands::Token { command } => {
let client = BrewlogClient::from_base_url(&cli.api_url)?; let client = BrewlogClient::from_base_url(&cli.api_url)?;
tokens::run(&client, command).await tokens::run(&client, command).await

View file

@ -0,0 +1,90 @@
use anyhow::Result;
use clap::{Args, Subcommand};
use super::macros::{define_delete_command, define_get_command};
use super::print_json;
use crate::domain::ids::{BagId, BrewId, GearId};
use crate::infrastructure::client::BrewlogClient;
#[derive(Debug, Subcommand)]
pub enum BrewCommands {
/// Add a new brew
Add(AddBrewCommand),
/// List all brews
List(ListBrewsCommand),
/// Get a brew by ID
Get(GetBrewCommand),
/// Delete a brew
Delete(DeleteBrewCommand),
}
pub async fn run(client: &BrewlogClient, cmd: BrewCommands) -> Result<()> {
match cmd {
BrewCommands::Add(c) => add_brew(client, c).await,
BrewCommands::List(c) => list_brews(client, c).await,
BrewCommands::Get(c) => get_brew(client, c).await,
BrewCommands::Delete(c) => delete_brew(client, c).await,
}
}
#[derive(Debug, Args)]
pub struct AddBrewCommand {
/// ID of the bag to brew from
#[arg(long)]
pub bag_id: i64,
/// Amount of coffee in grams
#[arg(long, default_value = "15.0")]
pub coffee_weight: f64,
/// ID of the grinder to use
#[arg(long)]
pub grinder_id: i64,
/// Grind setting (e.g., 6.0 or 7.5)
#[arg(long, default_value = "6.0")]
pub grind_setting: f64,
/// ID of the brewer to use
#[arg(long)]
pub brewer_id: i64,
/// Volume of water in ml
#[arg(long, default_value = "250")]
pub water_volume: i32,
/// Water temperature in Celsius
#[arg(long, default_value = "91.0")]
pub water_temp: f64,
}
pub async fn add_brew(client: &BrewlogClient, command: AddBrewCommand) -> Result<()> {
let brew = client
.brews()
.create(
BagId::new(command.bag_id),
command.coffee_weight,
GearId::new(command.grinder_id),
command.grind_setting,
GearId::new(command.brewer_id),
command.water_volume,
command.water_temp,
)
.await?;
print_json(&brew)
}
#[derive(Debug, Args)]
pub struct ListBrewsCommand {
/// Filter by bag ID
#[arg(long)]
pub bag_id: Option<i64>,
}
pub async fn list_brews(client: &BrewlogClient, command: ListBrewsCommand) -> Result<()> {
let brews = client.brews().list(command.bag_id.map(BagId::new)).await?;
print_json(&brews)
}
define_get_command!(GetBrewCommand, get_brew, BrewId, brews);
define_delete_command!(DeleteBrewCommand, delete_brew, BrewId, brews, "brew");

View file

@ -1,4 +1,5 @@
pub mod bags; pub mod bags;
pub mod brews;
pub mod gear; pub mod gear;
mod macros; mod macros;
pub mod roasters; pub mod roasters;
@ -8,6 +9,7 @@ pub mod tokens;
use std::net::SocketAddr; use std::net::SocketAddr;
use bags::BagCommands; use bags::BagCommands;
use brews::BrewCommands;
use clap::{Args, Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
use gear::GearCommands; use gear::GearCommands;
use roasters::RoasterCommands; use roasters::RoasterCommands;
@ -58,6 +60,12 @@ pub enum Commands {
command: GearCommands, command: GearCommands,
}, },
/// Manage brews
Brew {
#[command(subcommand)]
command: BrewCommands,
},
/// Manage API tokens /// Manage API tokens
Token { Token {
#[command(subcommand)] #[command(subcommand)]