refactor(cli): restructure commands from flat to nested subcommands
Change CLI structure from `brewlog {verb}-{entity}` to `brewlog {entity} {verb}`:
- brewlog add-roaster → brewlog roaster add
- brewlog list-bags → brewlog bag list
- brewlog create-token → brewlog token create
- etc.
Each entity module now owns its subcommand enum and dispatch logic,
simplifying main.rs and improving discoverability via `brewlog {entity} --help`.
- Add RoasterCommands, RoastCommands, BagCommands, GearCommands, TokenCommands enums
- Add run() dispatcher to each entity module
- Simplify top-level Commands enum to delegate to entity modules
- Update all CLI tests and bootstrap script
This commit is contained in:
parent
4edc66f44a
commit
0090c4ba43
14 changed files with 392 additions and 285 deletions
|
|
@ -3,7 +3,7 @@ set -euo pipefail
|
||||||
|
|
||||||
cargo build
|
cargo build
|
||||||
|
|
||||||
BREWLOG_TOKEN="$(./target/debug/brewlog create-token --name "bootstrap-token" --username admin --password password | grep -Po "BREWLOG_TOKEN=\K.+$")"
|
BREWLOG_TOKEN="$(./target/debug/brewlog token create --name "bootstrap-token" --username admin --password password | grep -Po "BREWLOG_TOKEN=\K.+$")"
|
||||||
export BREWLOG_TOKEN
|
export BREWLOG_TOKEN
|
||||||
|
|
||||||
if [[ -z "$BREWLOG_TOKEN" ]]; then
|
if [[ -z "$BREWLOG_TOKEN" ]]; then
|
||||||
|
|
@ -12,15 +12,15 @@ if [[ -z "$BREWLOG_TOKEN" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Tim Wendelboe (Norway)
|
# Tim Wendelboe (Norway)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Tim Wendelboe" \
|
--name "Tim Wendelboe" \
|
||||||
--country "Norway" \
|
--country "Norway" \
|
||||||
--city "Oslo" \
|
--city "Oslo" \
|
||||||
--homepage "https://timwendelboe.no" \
|
--homepage "https://timwendelboe.no" \
|
||||||
--notes "World-renowned Nordic micro-roastery dedicated to clarity and sustainability."
|
--notes "World-renowned Nordic micro-roastery dedicated to clarity and sustainability."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Tim Wendelboe") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Tim Wendelboe") | .id')" \
|
||||||
--name "Ben Saïd Natural" \
|
--name "Ben Saïd Natural" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Sidamo" \
|
--region "Sidamo" \
|
||||||
|
|
@ -28,8 +28,8 @@ fi
|
||||||
--process "Natural" \
|
--process "Natural" \
|
||||||
--tasting-notes "Bergamot, Apricot, Floral"
|
--tasting-notes "Bergamot, Apricot, Floral"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Tim Wendelboe") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Tim Wendelboe") | .id')" \
|
||||||
--name "Finca Tamana Washed" \
|
--name "Finca Tamana Washed" \
|
||||||
--origin "Colombia" \
|
--origin "Colombia" \
|
||||||
--region "El Pital, Huila" \
|
--region "El Pital, Huila" \
|
||||||
|
|
@ -39,15 +39,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Coffee Collective (Denmark)
|
# Coffee Collective (Denmark)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Coffee Collective" \
|
--name "Coffee Collective" \
|
||||||
--country "Denmark" \
|
--country "Denmark" \
|
||||||
--city "Copenhagen" \
|
--city "Copenhagen" \
|
||||||
--homepage "https://coffeecollective.dk" \
|
--homepage "https://coffeecollective.dk" \
|
||||||
--notes "Pioneers of transparency and sustainability; multi-time Nordic roaster award winners."
|
--notes "Pioneers of transparency and sustainability; multi-time Nordic roaster award winners."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Coffee Collective") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Coffee Collective") | .id')" \
|
||||||
--name "Daterra Sweet Collection" \
|
--name "Daterra Sweet Collection" \
|
||||||
--origin "Brazil" \
|
--origin "Brazil" \
|
||||||
--region "Cerrado" \
|
--region "Cerrado" \
|
||||||
|
|
@ -55,8 +55,8 @@ fi
|
||||||
--process "Pulped Natural" \
|
--process "Pulped Natural" \
|
||||||
--tasting-notes "Hazelnut, Milk Chocolate, Yellow Fruit"
|
--tasting-notes "Hazelnut, Milk Chocolate, Yellow Fruit"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Coffee Collective") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Coffee Collective") | .id')" \
|
||||||
--name "Kieni" \
|
--name "Kieni" \
|
||||||
--origin "Kenya" \
|
--origin "Kenya" \
|
||||||
--region "Nyeri" \
|
--region "Nyeri" \
|
||||||
|
|
@ -66,15 +66,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Drop Coffee (Sweden)
|
# Drop Coffee (Sweden)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Drop Coffee" \
|
--name "Drop Coffee" \
|
||||||
--country "Sweden" \
|
--country "Sweden" \
|
||||||
--city "Stockholm" \
|
--city "Stockholm" \
|
||||||
--homepage "https://dropcoffee.com" \
|
--homepage "https://dropcoffee.com" \
|
||||||
--notes "Award-winning Swedish roastery prized for its elegance and clean Scandinavian style."
|
--notes "Award-winning Swedish roastery prized for its elegance and clean Scandinavian style."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Drop Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Drop Coffee") | .id')" \
|
||||||
--name "La Linda" \
|
--name "La Linda" \
|
||||||
--origin "Bolivia" \
|
--origin "Bolivia" \
|
||||||
--region "Caranavi" \
|
--region "Caranavi" \
|
||||||
|
|
@ -82,8 +82,8 @@ fi
|
||||||
--process "Washed" \
|
--process "Washed" \
|
||||||
--tasting-notes "Red Apple, Caramel, Floral"
|
--tasting-notes "Red Apple, Caramel, Floral"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Drop Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Drop Coffee") | .id')" \
|
||||||
--name "El Sunzita" \
|
--name "El Sunzita" \
|
||||||
--origin "El Salvador" \
|
--origin "El Salvador" \
|
||||||
--region "Ahuachapan" \
|
--region "Ahuachapan" \
|
||||||
|
|
@ -93,15 +93,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# La Cabra (Denmark)
|
# La Cabra (Denmark)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "La Cabra" \
|
--name "La Cabra" \
|
||||||
--country "Denmark" \
|
--country "Denmark" \
|
||||||
--city "Aarhus" \
|
--city "Aarhus" \
|
||||||
--homepage "https://www.lacabra.dk" \
|
--homepage "https://www.lacabra.dk" \
|
||||||
--notes "Scandinavian minimalist roastery known for clarity and innovative sourcing."
|
--notes "Scandinavian minimalist roastery known for clarity and innovative sourcing."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="La Cabra") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="La Cabra") | .id')" \
|
||||||
--name "Halo Beriti" \
|
--name "Halo Beriti" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Yirgacheffe" \
|
--region "Yirgacheffe" \
|
||||||
|
|
@ -109,8 +109,8 @@ fi
|
||||||
--process "Washed" \
|
--process "Washed" \
|
||||||
--tasting-notes "Jasmine, Lemon, Stone Fruit"
|
--tasting-notes "Jasmine, Lemon, Stone Fruit"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="La Cabra") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="La Cabra") | .id')" \
|
||||||
--name "Cerro Azul" \
|
--name "Cerro Azul" \
|
||||||
--origin "Colombia" \
|
--origin "Colombia" \
|
||||||
--region "Valle del Cauca" \
|
--region "Valle del Cauca" \
|
||||||
|
|
@ -120,15 +120,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# April Coffee (Denmark)
|
# April Coffee (Denmark)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "April Coffee" \
|
--name "April Coffee" \
|
||||||
--country "Denmark" \
|
--country "Denmark" \
|
||||||
--city "Copenhagen" \
|
--city "Copenhagen" \
|
||||||
--homepage "https://aprilcoffeeroasters.com" \
|
--homepage "https://aprilcoffeeroasters.com" \
|
||||||
--notes "Modern approach to Nordic coffee, emphasizing transparency and traceability."
|
--notes "Modern approach to Nordic coffee, emphasizing transparency and traceability."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="April Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="April Coffee") | .id')" \
|
||||||
--name "El Salvador Pacamara" \
|
--name "El Salvador Pacamara" \
|
||||||
--origin "El Salvador" \
|
--origin "El Salvador" \
|
||||||
--region "Santa Ana" \
|
--region "Santa Ana" \
|
||||||
|
|
@ -136,8 +136,8 @@ fi
|
||||||
--process "Honey" \
|
--process "Honey" \
|
||||||
--tasting-notes "Grapefruit, Sugar Cane, Plum"
|
--tasting-notes "Grapefruit, Sugar Cane, Plum"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="April Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="April Coffee") | .id')" \
|
||||||
--name "Guji Highland" \
|
--name "Guji Highland" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Guji" \
|
--region "Guji" \
|
||||||
|
|
@ -147,15 +147,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Assembly Coffee (UK)
|
# Assembly Coffee (UK)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Assembly Coffee" \
|
--name "Assembly Coffee" \
|
||||||
--country "UK" \
|
--country "UK" \
|
||||||
--city "London" \
|
--city "London" \
|
||||||
--homepage "https://assemblycoffee.co.uk" \
|
--homepage "https://assemblycoffee.co.uk" \
|
||||||
--notes "Based in Brixton, Assembly focuses on collaborative sourcing and education."
|
--notes "Based in Brixton, Assembly focuses on collaborative sourcing and education."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Assembly Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Assembly Coffee") | .id')" \
|
||||||
--name "Kochere" \
|
--name "Kochere" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Yirgacheffe" \
|
--region "Yirgacheffe" \
|
||||||
|
|
@ -163,8 +163,8 @@ fi
|
||||||
--process "Washed" \
|
--process "Washed" \
|
||||||
--tasting-notes "Peach, Lemon, Jasmine"
|
--tasting-notes "Peach, Lemon, Jasmine"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Assembly Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Assembly Coffee") | .id')" \
|
||||||
--name "La Laja" \
|
--name "La Laja" \
|
||||||
--origin "Mexico" \
|
--origin "Mexico" \
|
||||||
--region "Veracruz" \
|
--region "Veracruz" \
|
||||||
|
|
@ -174,15 +174,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Square Mile (UK)
|
# Square Mile (UK)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Square Mile Coffee" \
|
--name "Square Mile Coffee" \
|
||||||
--country "UK" \
|
--country "UK" \
|
||||||
--city "London" \
|
--city "London" \
|
||||||
--homepage "https://squaremilecoffee.com" \
|
--homepage "https://squaremilecoffee.com" \
|
||||||
--notes "One of London's pioneers; delivers balanced and clear, fruit-forward coffees."
|
--notes "One of London's pioneers; delivers balanced and clear, fruit-forward coffees."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Square Mile Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Square Mile Coffee") | .id')" \
|
||||||
--name "Red Brick Espresso" \
|
--name "Red Brick Espresso" \
|
||||||
--origin "Blend" \
|
--origin "Blend" \
|
||||||
--region "Multiple Origins" \
|
--region "Multiple Origins" \
|
||||||
|
|
@ -190,8 +190,8 @@ fi
|
||||||
--process "Washed, Natural" \
|
--process "Washed, Natural" \
|
||||||
--tasting-notes "Berry, Chocolate, Citrus"
|
--tasting-notes "Berry, Chocolate, Citrus"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Square Mile Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Square Mile Coffee") | .id')" \
|
||||||
--name "Kamwangi" \
|
--name "Kamwangi" \
|
||||||
--origin "Kenya" \
|
--origin "Kenya" \
|
||||||
--region "Kirinyaga" \
|
--region "Kirinyaga" \
|
||||||
|
|
@ -201,15 +201,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Dak Coffee Roasters (Netherlands)
|
# Dak Coffee Roasters (Netherlands)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Dak Coffee Roasters" \
|
--name "Dak Coffee Roasters" \
|
||||||
--country "Netherlands" \
|
--country "Netherlands" \
|
||||||
--city "Amsterdam" \
|
--city "Amsterdam" \
|
||||||
--homepage "https://www.dakcoffeeroasters.com" \
|
--homepage "https://www.dakcoffeeroasters.com" \
|
||||||
--notes "Highly experimental Dutch roastery; celebrates vibrant acidity and alternative processing."
|
--notes "Highly experimental Dutch roastery; celebrates vibrant acidity and alternative processing."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Dak Coffee Roasters") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Dak Coffee Roasters") | .id')" \
|
||||||
--name "El Paraiso 92 Anaerobic" \
|
--name "El Paraiso 92 Anaerobic" \
|
||||||
--origin "Colombia" \
|
--origin "Colombia" \
|
||||||
--region "Cauca" \
|
--region "Cauca" \
|
||||||
|
|
@ -217,8 +217,8 @@ fi
|
||||||
--process "Thermal Shock Anaerobic" \
|
--process "Thermal Shock Anaerobic" \
|
||||||
--tasting-notes "Passionfruit, Raspberry, Yogurt"
|
--tasting-notes "Passionfruit, Raspberry, Yogurt"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Dak Coffee Roasters") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Dak Coffee Roasters") | .id')" \
|
||||||
--name "Oreti SL28" \
|
--name "Oreti SL28" \
|
||||||
--origin "Kenya" \
|
--origin "Kenya" \
|
||||||
--region "Kirinyaga" \
|
--region "Kirinyaga" \
|
||||||
|
|
@ -228,15 +228,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Bonanza Coffee (Germany)
|
# Bonanza Coffee (Germany)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Bonanza Coffee" \
|
--name "Bonanza Coffee" \
|
||||||
--country "Germany" \
|
--country "Germany" \
|
||||||
--city "Berlin" \
|
--city "Berlin" \
|
||||||
--homepage "https://www.bonanzacoffee.de" \
|
--homepage "https://www.bonanzacoffee.de" \
|
||||||
--notes "Pioneering Berlin roastery focused on brightness, balance, and freshness."
|
--notes "Pioneering Berlin roastery focused on brightness, balance, and freshness."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Bonanza Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Bonanza Coffee") | .id')" \
|
||||||
--name "Gatomboya" \
|
--name "Gatomboya" \
|
||||||
--origin "Kenya" \
|
--origin "Kenya" \
|
||||||
--region "Nyeri" \
|
--region "Nyeri" \
|
||||||
|
|
@ -244,8 +244,8 @@ fi
|
||||||
--process "Washed" \
|
--process "Washed" \
|
||||||
--tasting-notes "Blackcurrant, Lime, Tomato"
|
--tasting-notes "Blackcurrant, Lime, Tomato"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Bonanza Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Bonanza Coffee") | .id')" \
|
||||||
--name "Los Pirineos" \
|
--name "Los Pirineos" \
|
||||||
--origin "El Salvador" \
|
--origin "El Salvador" \
|
||||||
--region "Usulután" \
|
--region "Usulután" \
|
||||||
|
|
@ -255,15 +255,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Friedhats (Netherlands)
|
# Friedhats (Netherlands)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Friedhats" \
|
--name "Friedhats" \
|
||||||
--country "Netherlands" \
|
--country "Netherlands" \
|
||||||
--city "Amsterdam" \
|
--city "Amsterdam" \
|
||||||
--homepage "https://friedhats.com" \
|
--homepage "https://friedhats.com" \
|
||||||
--notes "Quirky branding meets serious, awarded, fruit-forward coffees from Amsterdam."
|
--notes "Quirky branding meets serious, awarded, fruit-forward coffees from Amsterdam."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Friedhats") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Friedhats") | .id')" \
|
||||||
--name "Sidamo Guji" \
|
--name "Sidamo Guji" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Guji" \
|
--region "Guji" \
|
||||||
|
|
@ -271,8 +271,8 @@ fi
|
||||||
--process "Natural" \
|
--process "Natural" \
|
||||||
--tasting-notes "Peach, Raspberry, Rosehip"
|
--tasting-notes "Peach, Raspberry, Rosehip"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Friedhats") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Friedhats") | .id')" \
|
||||||
--name "La Esmeralda Geisha" \
|
--name "La Esmeralda Geisha" \
|
||||||
--origin "Panama" \
|
--origin "Panama" \
|
||||||
--region "Boquete" \
|
--region "Boquete" \
|
||||||
|
|
@ -282,15 +282,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Origin Coffee (UK)
|
# Origin Coffee (UK)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Origin Coffee" \
|
--name "Origin Coffee" \
|
||||||
--country "UK" \
|
--country "UK" \
|
||||||
--city "Porthleven" \
|
--city "Porthleven" \
|
||||||
--homepage "https://origincoffee.co.uk" \
|
--homepage "https://origincoffee.co.uk" \
|
||||||
--notes "Specialty roaster with close partnerships at origin; leading UK scene with cutting-edge lots."
|
--notes "Specialty roaster with close partnerships at origin; leading UK scene with cutting-edge lots."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Origin Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Origin Coffee") | .id')" \
|
||||||
--name "San Fermin" \
|
--name "San Fermin" \
|
||||||
--origin "Colombia" \
|
--origin "Colombia" \
|
||||||
--region "Tolima" \
|
--region "Tolima" \
|
||||||
|
|
@ -298,8 +298,8 @@ fi
|
||||||
--process "Washed" \
|
--process "Washed" \
|
||||||
--tasting-notes "Red Grape, Caramel, Blood Orange"
|
--tasting-notes "Red Grape, Caramel, Blood Orange"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Origin Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Origin Coffee") | .id')" \
|
||||||
--name "Aricha" \
|
--name "Aricha" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Yirgacheffe" \
|
--region "Yirgacheffe" \
|
||||||
|
|
@ -309,15 +309,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Dark Arts Coffee (UK)
|
# Dark Arts Coffee (UK)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Dark Arts Coffee" \
|
--name "Dark Arts Coffee" \
|
||||||
--country "UK" \
|
--country "UK" \
|
||||||
--city "London" \
|
--city "London" \
|
||||||
--homepage "https://www.darkartscoffee.co.uk" \
|
--homepage "https://www.darkartscoffee.co.uk" \
|
||||||
--notes "Playful, disruptive roaster with a cult following and flavor-forward offerings."
|
--notes "Playful, disruptive roaster with a cult following and flavor-forward offerings."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Dark Arts Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Dark Arts Coffee") | .id')" \
|
||||||
--name "Death to Decaf" \
|
--name "Death to Decaf" \
|
||||||
--origin "Brazil" \
|
--origin "Brazil" \
|
||||||
--region "Minas Gerais" \
|
--region "Minas Gerais" \
|
||||||
|
|
@ -325,8 +325,8 @@ fi
|
||||||
--process "Swiss Water Decaf" \
|
--process "Swiss Water Decaf" \
|
||||||
--tasting-notes "Cocoa, Cherry, Almond"
|
--tasting-notes "Cocoa, Cherry, Almond"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Dark Arts Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Dark Arts Coffee") | .id')" \
|
||||||
--name "Snoop" \
|
--name "Snoop" \
|
||||||
--origin "Guatemala" \
|
--origin "Guatemala" \
|
||||||
--region "Huehuetenango" \
|
--region "Huehuetenango" \
|
||||||
|
|
@ -336,15 +336,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# KAWA Coffee (France)
|
# KAWA Coffee (France)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "KAWA Coffee" \
|
--name "KAWA Coffee" \
|
||||||
--country "France" \
|
--country "France" \
|
||||||
--city "Paris" \
|
--city "Paris" \
|
||||||
--homepage "https://www.kawa.coffee" \
|
--homepage "https://www.kawa.coffee" \
|
||||||
--notes "One of Paris’ most exciting specialty roasteries, known for unusual and competition-level lots."
|
--notes "One of Paris’ most exciting specialty roasteries, known for unusual and competition-level lots."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="KAWA Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="KAWA Coffee") | .id')" \
|
||||||
--name "Sudan Rume" \
|
--name "Sudan Rume" \
|
||||||
--origin "Colombia" \
|
--origin "Colombia" \
|
||||||
--region "Cauca" \
|
--region "Cauca" \
|
||||||
|
|
@ -352,8 +352,8 @@ fi
|
||||||
--process "Natural" \
|
--process "Natural" \
|
||||||
--tasting-notes "Strawberry, Cinnamon, Grape"
|
--tasting-notes "Strawberry, Cinnamon, Grape"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="KAWA Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="KAWA Coffee") | .id')" \
|
||||||
--name "Arbegona" \
|
--name "Arbegona" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Sidama" \
|
--region "Sidama" \
|
||||||
|
|
@ -363,15 +363,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Stow Coffee (Slovenia)
|
# Stow Coffee (Slovenia)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Stow Coffee" \
|
--name "Stow Coffee" \
|
||||||
--country "Slovenia" \
|
--country "Slovenia" \
|
||||||
--city "Ljubljana" \
|
--city "Ljubljana" \
|
||||||
--homepage "https://www.stowcoffee.com" \
|
--homepage "https://www.stowcoffee.com" \
|
||||||
--notes "Slovenia’s specialty leader, awarded for pure, brightly acidic profiles and innovation."
|
--notes "Slovenia’s specialty leader, awarded for pure, brightly acidic profiles and innovation."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Stow Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Stow Coffee") | .id')" \
|
||||||
--name "Santa Barbara" \
|
--name "Santa Barbara" \
|
||||||
--origin "Honduras" \
|
--origin "Honduras" \
|
||||||
--region "Santa Barbara" \
|
--region "Santa Barbara" \
|
||||||
|
|
@ -379,8 +379,8 @@ fi
|
||||||
--process "Honey" \
|
--process "Honey" \
|
||||||
--tasting-notes "Red Currant, Honeydew, Cocoa"
|
--tasting-notes "Red Currant, Honeydew, Cocoa"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Stow Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Stow Coffee") | .id')" \
|
||||||
--name "Suke Quto" \
|
--name "Suke Quto" \
|
||||||
--origin "Ethiopia" \
|
--origin "Ethiopia" \
|
||||||
--region "Guji" \
|
--region "Guji" \
|
||||||
|
|
@ -390,15 +390,15 @@ fi
|
||||||
|
|
||||||
|
|
||||||
# Bows Coffee (Canada)
|
# Bows Coffee (Canada)
|
||||||
./target/debug/brewlog add-roaster \
|
./target/debug/brewlog roaster add \
|
||||||
--name "Bows Coffee" \
|
--name "Bows Coffee" \
|
||||||
--country "Canada" \
|
--country "Canada" \
|
||||||
--city "Victoria" \
|
--city "Victoria" \
|
||||||
--homepage "https://bowscoffee.com" \
|
--homepage "https://bowscoffee.com" \
|
||||||
--notes "Canadian micro-roaster with focus on clarity, complexity, and ethical sourcing."
|
--notes "Canadian micro-roaster with focus on clarity, complexity, and ethical sourcing."
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Bows Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Bows Coffee") | .id')" \
|
||||||
--name "La Chumeca" \
|
--name "La Chumeca" \
|
||||||
--origin "Costa Rica" \
|
--origin "Costa Rica" \
|
||||||
--region "Tarrazú" \
|
--region "Tarrazú" \
|
||||||
|
|
@ -406,8 +406,8 @@ fi
|
||||||
--process "White Honey" \
|
--process "White Honey" \
|
||||||
--tasting-notes "Mandarin, Honeycomb, Almond"
|
--tasting-notes "Mandarin, Honeycomb, Almond"
|
||||||
|
|
||||||
./target/debug/brewlog add-roast \
|
./target/debug/brewlog roast add \
|
||||||
--roaster-id "$(./target/debug/brewlog list-roasters | jq -r '.[] | select(.name=="Bows Coffee") | .id')" \
|
--roaster-id "$(./target/debug/brewlog roaster list | jq -r '.[] | select(.name=="Bows Coffee") | .id')" \
|
||||||
--name "Simbi" \
|
--name "Simbi" \
|
||||||
--origin "Rwanda" \
|
--origin "Rwanda" \
|
||||||
--region "Huye" \
|
--region "Huye" \
|
||||||
|
|
@ -420,74 +420,74 @@ fi
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Tim Wendelboe - Ben Saïd Natural (250g)
|
# Tim Wendelboe - Ben Saïd Natural (250g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Ben Saïd Natural") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Ben Saïd Natural") | .id')" \
|
||||||
--roast-date "2026-01-15" \
|
--roast-date "2026-01-15" \
|
||||||
--amount 250
|
--amount 250
|
||||||
|
|
||||||
# Tim Wendelboe - Finca Tamana Washed (350g)
|
# Tim Wendelboe - Finca Tamana Washed (350g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Finca Tamana Washed") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Finca Tamana Washed") | .id')" \
|
||||||
--roast-date "2026-01-18" \
|
--roast-date "2026-01-18" \
|
||||||
--amount 350
|
--amount 350
|
||||||
|
|
||||||
# Coffee Collective - Daterra Sweet Collection (200g)
|
# Coffee Collective - Daterra Sweet Collection (200g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Daterra Sweet Collection") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Daterra Sweet Collection") | .id')" \
|
||||||
--roast-date "2026-01-10" \
|
--roast-date "2026-01-10" \
|
||||||
--amount 200
|
--amount 200
|
||||||
|
|
||||||
# Drop Coffee - La Linda (500g)
|
# Drop Coffee - La Linda (500g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="La Linda") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Linda") | .id')" \
|
||||||
--roast-date "2026-01-20" \
|
--roast-date "2026-01-20" \
|
||||||
--amount 500
|
--amount 500
|
||||||
|
|
||||||
# La Cabra - Halo Beriti (150g)
|
# La Cabra - Halo Beriti (150g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Halo Beriti") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Halo Beriti") | .id')" \
|
||||||
--roast-date "2026-01-12" \
|
--roast-date "2026-01-12" \
|
||||||
--amount 150
|
--amount 150
|
||||||
|
|
||||||
# April Coffee - Guji Highland (300g)
|
# April Coffee - Guji Highland (300g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Guji Highland") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Guji Highland") | .id')" \
|
||||||
--roast-date "2026-01-22" \
|
--roast-date "2026-01-22" \
|
||||||
--amount 300
|
--amount 300
|
||||||
|
|
||||||
# Assembly Coffee - Kochere (250g)
|
# Assembly Coffee - Kochere (250g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Kochere") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Kochere") | .id')" \
|
||||||
--roast-date "2026-01-08" \
|
--roast-date "2026-01-08" \
|
||||||
--amount 250
|
--amount 250
|
||||||
|
|
||||||
# Square Mile Coffee - Red Brick Espresso (400g)
|
# Square Mile Coffee - Red Brick Espresso (400g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Red Brick Espresso") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Red Brick Espresso") | .id')" \
|
||||||
--roast-date "2026-01-25" \
|
--roast-date "2026-01-25" \
|
||||||
--amount 400
|
--amount 400
|
||||||
|
|
||||||
# Dak Coffee Roasters - El Paraiso 92 Anaerobic (100g - small competition lot)
|
# Dak Coffee Roasters - El Paraiso 92 Anaerobic (100g - small competition lot)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="El Paraiso 92 Anaerobic") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="El Paraiso 92 Anaerobic") | .id')" \
|
||||||
--roast-date "2026-01-28" \
|
--roast-date "2026-01-28" \
|
||||||
--amount 100
|
--amount 100
|
||||||
|
|
||||||
# Bonanza Coffee - Gatomboya (175g)
|
# Bonanza Coffee - Gatomboya (175g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Gatomboya") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Gatomboya") | .id')" \
|
||||||
--roast-date "2026-01-05" \
|
--roast-date "2026-01-05" \
|
||||||
--amount 175
|
--amount 175
|
||||||
|
|
||||||
# Stow Coffee - Suke Quto (225g)
|
# Stow Coffee - Suke Quto (225g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Suke Quto") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Suke Quto") | .id')" \
|
||||||
--roast-date "2026-01-30" \
|
--roast-date "2026-01-30" \
|
||||||
--amount 225
|
--amount 225
|
||||||
|
|
||||||
# Bows Coffee - Simbi (450g)
|
# Bows Coffee - Simbi (450g)
|
||||||
./target/debug/brewlog add-bag \
|
./target/debug/brewlog bag add \
|
||||||
--roast-id "$(./target/debug/brewlog list-roasts | jq -r '.[] | select(.name=="Simbi") | .id')" \
|
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Simbi") | .id')" \
|
||||||
--roast-date "2026-01-14" \
|
--roast-date "2026-01-14" \
|
||||||
--amount 450
|
--amount 450
|
||||||
|
|
||||||
|
|
@ -496,26 +496,26 @@ fi
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Finish Gatomboya bag (oldest - Jan 5)
|
# Finish Gatomboya bag (oldest - Jan 5)
|
||||||
./target/debug/brewlog update-bag \
|
./target/debug/brewlog bag update \
|
||||||
--id "$(./target/debug/brewlog list-bags | jq -r '.[] | select(.roast_name=="Gatomboya") | .id')" \
|
--id "$(./target/debug/brewlog bag list | jq -r '.[] | select(.roast_name=="Gatomboya") | .id')" \
|
||||||
--closed true \
|
--closed true \
|
||||||
--finished-at "2026-01-20"
|
--finished-at "2026-01-20"
|
||||||
|
|
||||||
# Finish Kochere bag (Jan 8)
|
# Finish Kochere bag (Jan 8)
|
||||||
./target/debug/brewlog update-bag \
|
./target/debug/brewlog bag update \
|
||||||
--id "$(./target/debug/brewlog list-bags | jq -r '.[] | select(.roast_name=="Kochere") | .id')" \
|
--id "$(./target/debug/brewlog bag list | jq -r '.[] | select(.roast_name=="Kochere") | .id')" \
|
||||||
--closed true \
|
--closed true \
|
||||||
--finished-at "2026-01-22"
|
--finished-at "2026-01-22"
|
||||||
|
|
||||||
# Finish Daterra Sweet Collection bag (Jan 10)
|
# Finish Daterra Sweet Collection bag (Jan 10)
|
||||||
./target/debug/brewlog update-bag \
|
./target/debug/brewlog bag update \
|
||||||
--id "$(./target/debug/brewlog list-bags | jq -r '.[] | select(.roast_name=="Daterra Sweet Collection") | .id')" \
|
--id "$(./target/debug/brewlog bag list | jq -r '.[] | select(.roast_name=="Daterra Sweet Collection") | .id')" \
|
||||||
--closed true \
|
--closed true \
|
||||||
--finished-at "2026-01-25"
|
--finished-at "2026-01-25"
|
||||||
|
|
||||||
# Finish Halo Beriti bag (Jan 12)
|
# Finish Halo Beriti bag (Jan 12)
|
||||||
./target/debug/brewlog update-bag \
|
./target/debug/brewlog bag update \
|
||||||
--id "$(./target/debug/brewlog list-bags | jq -r '.[] | select(.roast_name=="Halo Beriti") | .id')" \
|
--id "$(./target/debug/brewlog bag list | jq -r '.[] | select(.roast_name=="Halo Beriti") | .id')" \
|
||||||
--closed true \
|
--closed true \
|
||||||
--finished-at "2026-01-28"
|
--finished-at "2026-01-28"
|
||||||
|
|
||||||
|
|
@ -524,32 +524,33 @@ fi
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Grinders
|
# Grinders
|
||||||
./target/debug/brewlog add-gear \
|
./target/debug/brewlog gear add \
|
||||||
--category "grinder" \
|
--category "grinder" \
|
||||||
--make "Comandante" \
|
--make "Comandante" \
|
||||||
--model "C40 MK4"
|
--model "C40 MK4"
|
||||||
|
|
||||||
./target/debug/brewlog add-gear \
|
./target/debug/brewlog gear add \
|
||||||
--category "grinder" \
|
--category "grinder" \
|
||||||
--make "1Zpresso" \
|
--make "1Zpresso" \
|
||||||
--model "J-Max"
|
--model "J-Max"
|
||||||
|
|
||||||
# Brewers
|
# Brewers
|
||||||
./target/debug/brewlog add-gear \
|
./target/debug/brewlog gear add \
|
||||||
--category "brewer" \
|
--category "brewer" \
|
||||||
--make "Hario" \
|
--make "Hario" \
|
||||||
--model "V60 02"
|
--model "V60 02"
|
||||||
|
|
||||||
./target/debug/brewlog add-gear \
|
./target/debug/brewlog gear add \
|
||||||
--category "brewer" \
|
--category "brewer" \
|
||||||
--make "AeroPress" \
|
--make "AeroPress" \
|
||||||
--model "Original"
|
--model "Original"
|
||||||
|
|
||||||
./target/debug/brewlog add-gear \
|
./target/debug/brewlog gear add \
|
||||||
--category "brewer" \
|
--category "brewer" \
|
||||||
--make "Fellow" \
|
--make "Fellow" \
|
||||||
--model "Stagg XF"
|
--model "Stagg XF"
|
||||||
|
|
||||||
|
echo
|
||||||
echo "Bootstrapped database"
|
echo "Bootstrapped database"
|
||||||
echo
|
echo
|
||||||
echo "Set token $BREWLOG_TOKEN to use the data added here."
|
echo "Set token $BREWLOG_TOKEN to use the data added here."
|
||||||
52
src/main.rs
52
src/main.rs
|
|
@ -21,43 +21,25 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Commands::Serve(cmd) => run_server(cmd).await,
|
Commands::Serve(cmd) => run_server(cmd).await,
|
||||||
command => {
|
Commands::Roaster { command } => {
|
||||||
let client = BrewlogClient::from_base_url(&cli.api_url)?;
|
let client = BrewlogClient::from_base_url(&cli.api_url)?;
|
||||||
match command {
|
roasters::run(&client, command).await
|
||||||
// Tokens
|
|
||||||
Commands::CreateToken(cmd) => tokens::create_token(&client, cmd).await,
|
|
||||||
Commands::ListTokens => tokens::list_tokens(&client).await,
|
|
||||||
Commands::RevokeToken(cmd) => tokens::revoke_token(&client, cmd).await,
|
|
||||||
|
|
||||||
// Roasters
|
|
||||||
Commands::AddRoaster(cmd) => roasters::add_roaster(&client, cmd).await,
|
|
||||||
Commands::ListRoasters => roasters::list_roasters(&client).await,
|
|
||||||
Commands::GetRoaster(cmd) => roasters::get_roaster(&client, cmd).await,
|
|
||||||
Commands::UpdateRoaster(cmd) => roasters::update_roaster(&client, cmd).await,
|
|
||||||
Commands::DeleteRoaster(cmd) => roasters::delete_roaster(&client, cmd).await,
|
|
||||||
|
|
||||||
// Roasts
|
|
||||||
Commands::AddRoast(cmd) => roasts::add_roast(&client, cmd).await,
|
|
||||||
Commands::ListRoasts(cmd) => roasts::list_roasts(&client, cmd).await,
|
|
||||||
Commands::GetRoast(cmd) => roasts::get_roast(&client, cmd).await,
|
|
||||||
Commands::DeleteRoast(cmd) => roasts::delete_roast(&client, cmd).await,
|
|
||||||
|
|
||||||
// Bags
|
|
||||||
Commands::AddBag(cmd) => bags::add_bag(&client, cmd).await,
|
|
||||||
Commands::ListBags(cmd) => bags::list_bags(&client, cmd).await,
|
|
||||||
Commands::GetBag(cmd) => bags::get_bag(&client, cmd).await,
|
|
||||||
Commands::UpdateBag(cmd) => bags::update_bag(&client, cmd).await,
|
|
||||||
Commands::DeleteBag(cmd) => bags::delete_bag(&client, cmd).await,
|
|
||||||
|
|
||||||
// Gear
|
|
||||||
Commands::AddGear(cmd) => gear::add_gear(&client, cmd).await,
|
|
||||||
Commands::ListGear(cmd) => gear::list_gear(&client, cmd).await,
|
|
||||||
Commands::GetGear(cmd) => gear::get_gear(&client, cmd).await,
|
|
||||||
Commands::UpdateGear(cmd) => gear::update_gear(&client, cmd).await,
|
|
||||||
Commands::DeleteGear(cmd) => gear::delete_gear(&client, cmd).await,
|
|
||||||
|
|
||||||
Commands::Serve(_) => unreachable!("serve command handled earlier"),
|
|
||||||
}
|
}
|
||||||
|
Commands::Roast { command } => {
|
||||||
|
let client = BrewlogClient::from_base_url(&cli.api_url)?;
|
||||||
|
roasts::run(&client, command).await
|
||||||
|
}
|
||||||
|
Commands::Bag { command } => {
|
||||||
|
let client = BrewlogClient::from_base_url(&cli.api_url)?;
|
||||||
|
bags::run(&client, command).await
|
||||||
|
}
|
||||||
|
Commands::Gear { command } => {
|
||||||
|
let client = BrewlogClient::from_base_url(&cli.api_url)?;
|
||||||
|
gear::run(&client, command).await
|
||||||
|
}
|
||||||
|
Commands::Token { command } => {
|
||||||
|
let client = BrewlogClient::from_base_url(&cli.api_url)?;
|
||||||
|
tokens::run(&client, command).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,35 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Args;
|
use clap::{Args, Subcommand};
|
||||||
|
|
||||||
use super::macros::{define_delete_command, define_get_command};
|
use super::macros::{define_delete_command, define_get_command};
|
||||||
use super::print_json;
|
use super::print_json;
|
||||||
use crate::domain::ids::{BagId, RoastId};
|
use crate::domain::ids::{BagId, RoastId};
|
||||||
use crate::infrastructure::client::BrewlogClient;
|
use crate::infrastructure::client::BrewlogClient;
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
pub enum BagCommands {
|
||||||
|
/// Add a new bag
|
||||||
|
Add(AddBagCommand),
|
||||||
|
/// List all bags
|
||||||
|
List(ListBagsCommand),
|
||||||
|
/// Get a bag by ID
|
||||||
|
Get(GetBagCommand),
|
||||||
|
/// Update a bag
|
||||||
|
Update(UpdateBagCommand),
|
||||||
|
/// Delete a bag
|
||||||
|
Delete(DeleteBagCommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(client: &BrewlogClient, cmd: BagCommands) -> Result<()> {
|
||||||
|
match cmd {
|
||||||
|
BagCommands::Add(c) => add_bag(client, c).await,
|
||||||
|
BagCommands::List(c) => list_bags(client, c).await,
|
||||||
|
BagCommands::Get(c) => get_bag(client, c).await,
|
||||||
|
BagCommands::Update(c) => update_bag(client, c).await,
|
||||||
|
BagCommands::Delete(c) => delete_bag(client, c).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
pub struct AddBagCommand {
|
pub struct AddBagCommand {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,35 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Args;
|
use clap::{Args, Subcommand};
|
||||||
|
|
||||||
use super::macros::{define_delete_command, define_get_command};
|
use super::macros::{define_delete_command, define_get_command};
|
||||||
use super::print_json;
|
use super::print_json;
|
||||||
use crate::domain::ids::GearId;
|
use crate::domain::ids::GearId;
|
||||||
use crate::infrastructure::client::BrewlogClient;
|
use crate::infrastructure::client::BrewlogClient;
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
pub enum GearCommands {
|
||||||
|
/// Add new gear
|
||||||
|
Add(AddGearCommand),
|
||||||
|
/// List all gear
|
||||||
|
List(ListGearCommand),
|
||||||
|
/// Get gear by ID
|
||||||
|
Get(GetGearCommand),
|
||||||
|
/// Update gear
|
||||||
|
Update(UpdateGearCommand),
|
||||||
|
/// Delete gear
|
||||||
|
Delete(DeleteGearCommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(client: &BrewlogClient, cmd: GearCommands) -> Result<()> {
|
||||||
|
match cmd {
|
||||||
|
GearCommands::Add(c) => add_gear(client, c).await,
|
||||||
|
GearCommands::List(c) => list_gear(client, c).await,
|
||||||
|
GearCommands::Get(c) => get_gear(client, c).await,
|
||||||
|
GearCommands::Update(c) => update_gear(client, c).await,
|
||||||
|
GearCommands::Delete(c) => delete_gear(client, c).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
pub struct AddGearCommand {
|
pub struct AddGearCommand {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ pub mod tokens;
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use bags::{AddBagCommand, DeleteBagCommand, GetBagCommand, ListBagsCommand, UpdateBagCommand};
|
use bags::BagCommands;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use gear::{AddGearCommand, DeleteGearCommand, GetGearCommand, ListGearCommand, UpdateGearCommand};
|
use gear::GearCommands;
|
||||||
use roasters::{AddRoasterCommand, DeleteRoasterCommand, GetRoasterCommand, UpdateRoasterCommand};
|
use roasters::RoasterCommands;
|
||||||
use roasts::{AddRoastCommand, DeleteRoastCommand, GetRoastCommand, ListRoastsCommand};
|
use roasts::RoastCommands;
|
||||||
use tokens::{CreateTokenCommand, RevokeTokenCommand};
|
use tokens::TokenCommands;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(author, version, about = "Track coffee roasts, brews, and cups", long_about = None)]
|
#[command(author, version, about = "Track coffee roasts, brews, and cups", long_about = None)]
|
||||||
|
|
@ -31,62 +31,38 @@ pub struct Cli {
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
#[command(name = "serve")]
|
/// Run the HTTP server
|
||||||
Serve(ServeCommand),
|
Serve(ServeCommand),
|
||||||
|
|
||||||
// Tokens
|
/// Manage roasters
|
||||||
#[command(name = "create-token")]
|
Roaster {
|
||||||
CreateToken(CreateTokenCommand),
|
#[command(subcommand)]
|
||||||
#[command(name = "list-tokens")]
|
command: RoasterCommands,
|
||||||
ListTokens,
|
},
|
||||||
#[command(name = "revoke-token")]
|
|
||||||
RevokeToken(RevokeTokenCommand),
|
|
||||||
|
|
||||||
// Roasters
|
/// Manage roasts
|
||||||
#[command(name = "add-roaster")]
|
Roast {
|
||||||
AddRoaster(AddRoasterCommand),
|
#[command(subcommand)]
|
||||||
#[command(name = "list-roasters")]
|
command: RoastCommands,
|
||||||
ListRoasters,
|
},
|
||||||
#[command(name = "get-roaster")]
|
|
||||||
GetRoaster(GetRoasterCommand),
|
|
||||||
#[command(name = "update-roaster")]
|
|
||||||
UpdateRoaster(UpdateRoasterCommand),
|
|
||||||
#[command(name = "delete-roaster")]
|
|
||||||
DeleteRoaster(DeleteRoasterCommand),
|
|
||||||
|
|
||||||
// Roasts
|
/// Manage bags
|
||||||
#[command(name = "add-roast")]
|
Bag {
|
||||||
AddRoast(AddRoastCommand),
|
#[command(subcommand)]
|
||||||
#[command(name = "list-roasts")]
|
command: BagCommands,
|
||||||
ListRoasts(ListRoastsCommand),
|
},
|
||||||
#[command(name = "get-roast")]
|
|
||||||
GetRoast(GetRoastCommand),
|
|
||||||
#[command(name = "delete-roast")]
|
|
||||||
DeleteRoast(DeleteRoastCommand),
|
|
||||||
|
|
||||||
// Bags
|
/// Manage gear
|
||||||
#[command(name = "add-bag")]
|
Gear {
|
||||||
AddBag(AddBagCommand),
|
#[command(subcommand)]
|
||||||
#[command(name = "list-bags")]
|
command: GearCommands,
|
||||||
ListBags(ListBagsCommand),
|
},
|
||||||
#[command(name = "get-bag")]
|
|
||||||
GetBag(GetBagCommand),
|
|
||||||
#[command(name = "update-bag")]
|
|
||||||
UpdateBag(UpdateBagCommand),
|
|
||||||
#[command(name = "delete-bag")]
|
|
||||||
DeleteBag(DeleteBagCommand),
|
|
||||||
|
|
||||||
// Gear
|
/// Manage API tokens
|
||||||
#[command(name = "add-gear")]
|
Token {
|
||||||
AddGear(AddGearCommand),
|
#[command(subcommand)]
|
||||||
#[command(name = "list-gear")]
|
command: TokenCommands,
|
||||||
ListGear(ListGearCommand),
|
},
|
||||||
#[command(name = "get-gear")]
|
|
||||||
GetGear(GetGearCommand),
|
|
||||||
#[command(name = "update-gear")]
|
|
||||||
UpdateGear(UpdateGearCommand),
|
|
||||||
#[command(name = "delete-gear")]
|
|
||||||
DeleteGear(DeleteGearCommand),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Args;
|
use clap::{Args, Subcommand};
|
||||||
|
|
||||||
use super::macros::{define_delete_command, define_get_command};
|
use super::macros::{define_delete_command, define_get_command};
|
||||||
use super::print_json;
|
use super::print_json;
|
||||||
|
|
@ -7,6 +7,30 @@ use crate::domain::ids::RoasterId;
|
||||||
use crate::domain::roasters::{NewRoaster, UpdateRoaster};
|
use crate::domain::roasters::{NewRoaster, UpdateRoaster};
|
||||||
use crate::infrastructure::client::BrewlogClient;
|
use crate::infrastructure::client::BrewlogClient;
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
pub enum RoasterCommands {
|
||||||
|
/// Add a new roaster
|
||||||
|
Add(AddRoasterCommand),
|
||||||
|
/// List all roasters
|
||||||
|
List,
|
||||||
|
/// Get a roaster by ID
|
||||||
|
Get(GetRoasterCommand),
|
||||||
|
/// Update a roaster
|
||||||
|
Update(UpdateRoasterCommand),
|
||||||
|
/// Delete a roaster
|
||||||
|
Delete(DeleteRoasterCommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(client: &BrewlogClient, cmd: RoasterCommands) -> Result<()> {
|
||||||
|
match cmd {
|
||||||
|
RoasterCommands::Add(c) => add_roaster(client, c).await,
|
||||||
|
RoasterCommands::List => list_roasters(client).await,
|
||||||
|
RoasterCommands::Get(c) => get_roaster(client, c).await,
|
||||||
|
RoasterCommands::Update(c) => update_roaster(client, c).await,
|
||||||
|
RoasterCommands::Delete(c) => delete_roaster(client, c).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
pub struct AddRoasterCommand {
|
pub struct AddRoasterCommand {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Args;
|
use clap::{Args, Subcommand};
|
||||||
|
|
||||||
use super::macros::{define_delete_command, define_get_command};
|
use super::macros::{define_delete_command, define_get_command};
|
||||||
use super::print_json;
|
use super::print_json;
|
||||||
|
|
@ -7,6 +7,27 @@ use crate::domain::ids::{RoastId, RoasterId};
|
||||||
use crate::domain::roasts::NewRoast;
|
use crate::domain::roasts::NewRoast;
|
||||||
use crate::infrastructure::client::BrewlogClient;
|
use crate::infrastructure::client::BrewlogClient;
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
pub enum RoastCommands {
|
||||||
|
/// Add a new roast
|
||||||
|
Add(AddRoastCommand),
|
||||||
|
/// List all roasts
|
||||||
|
List(ListRoastsCommand),
|
||||||
|
/// Get a roast by ID
|
||||||
|
Get(GetRoastCommand),
|
||||||
|
/// Delete a roast
|
||||||
|
Delete(DeleteRoastCommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(client: &BrewlogClient, cmd: RoastCommands) -> Result<()> {
|
||||||
|
match cmd {
|
||||||
|
RoastCommands::Add(c) => add_roast(client, c).await,
|
||||||
|
RoastCommands::List(c) => list_roasts(client, c).await,
|
||||||
|
RoastCommands::Get(c) => get_roast(client, c).await,
|
||||||
|
RoastCommands::Delete(c) => delete_roast(client, c).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
pub struct AddRoastCommand {
|
pub struct AddRoastCommand {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,29 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::Args;
|
use clap::{Args, Subcommand};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
use super::print_json;
|
use super::print_json;
|
||||||
use crate::domain::ids::TokenId;
|
use crate::domain::ids::TokenId;
|
||||||
use crate::infrastructure::client::BrewlogClient;
|
use crate::infrastructure::client::BrewlogClient;
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
pub enum TokenCommands {
|
||||||
|
/// Create a new API token
|
||||||
|
Create(CreateTokenCommand),
|
||||||
|
/// List all tokens
|
||||||
|
List,
|
||||||
|
/// Revoke a token
|
||||||
|
Revoke(RevokeTokenCommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(client: &BrewlogClient, cmd: TokenCommands) -> Result<()> {
|
||||||
|
match cmd {
|
||||||
|
TokenCommands::Create(c) => create_token(client, c).await,
|
||||||
|
TokenCommands::List => list_tokens(client).await,
|
||||||
|
TokenCommands::Revoke(c) => revoke_token(client, c).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
pub struct CreateTokenCommand {
|
pub struct CreateTokenCommand {
|
||||||
/// A descriptive name for this token
|
/// A descriptive name for this token
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,12 @@ use serde_json::Value;
|
||||||
fn test_add_bag_requires_authentication() {
|
fn test_add_bag_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["add-bag", "--roast-id", "123", "--amount", "250.0"], &[]);
|
let output = run_brewlog(
|
||||||
|
&["bag", "add", "--roast-id", "123", "--amount", "250.0"],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!output.status.success(), "add-bag without auth should fail");
|
assert!(!output.status.success(), "bag add without auth should fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -21,7 +24,8 @@ fn test_add_bag_with_authentication() {
|
||||||
// Test: Add Bag
|
// Test: Add Bag
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-bag",
|
"bag",
|
||||||
|
"add",
|
||||||
"--roast-id",
|
"--roast-id",
|
||||||
&roast_id,
|
&roast_id,
|
||||||
"--amount",
|
"--amount",
|
||||||
|
|
@ -44,11 +48,14 @@ fn test_add_bag_with_authentication() {
|
||||||
fn test_update_bag_requires_authentication() {
|
fn test_update_bag_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["update-bag", "--id", "123", "--remaining", "100.0"], &[]);
|
let output = run_brewlog(
|
||||||
|
&["bag", "update", "--id", "123", "--remaining", "100.0"],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"update-bag without auth should fail"
|
"bag update without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,7 +68,7 @@ fn test_update_bag_with_authentication() {
|
||||||
let roast_id = create_roast(&roaster_id, "Bag Update Roast", &token);
|
let roast_id = create_roast(&roaster_id, "Bag Update Roast", &token);
|
||||||
|
|
||||||
let bag_output = run_brewlog(
|
let bag_output = run_brewlog(
|
||||||
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
|
&["bag", "add", "--roast-id", &roast_id, "--amount", "250.0"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
||||||
|
|
@ -70,7 +77,8 @@ fn test_update_bag_with_authentication() {
|
||||||
// Test: Update Bag
|
// Test: Update Bag
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"update-bag",
|
"bag",
|
||||||
|
"update",
|
||||||
"--id",
|
"--id",
|
||||||
&bag_id,
|
&bag_id,
|
||||||
"--remaining",
|
"--remaining",
|
||||||
|
|
@ -92,7 +100,7 @@ fn test_update_bag_with_authentication() {
|
||||||
fn test_list_bags_works_without_authentication() {
|
fn test_list_bags_works_without_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
// Listing without roast_id might return all or empty, but should succeed (200 OK)
|
// Listing without roast_id might return all or empty, but should succeed (200 OK)
|
||||||
let output = run_brewlog(&["list-bags"], &[]);
|
let output = run_brewlog(&["bag", "list"], &[]);
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +113,7 @@ fn test_list_bags_shows_added_bag() {
|
||||||
let roast_id = create_roast(&roaster_id, "Bag List Roast", &token);
|
let roast_id = create_roast(&roaster_id, "Bag List Roast", &token);
|
||||||
|
|
||||||
let bag_output = run_brewlog(
|
let bag_output = run_brewlog(
|
||||||
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
|
&["bag", "add", "--roast-id", &roast_id, "--amount", "250.0"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
||||||
|
|
@ -113,7 +121,7 @@ fn test_list_bags_shows_added_bag() {
|
||||||
|
|
||||||
// Test: List Bags (Authenticated)
|
// Test: List Bags (Authenticated)
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&["list-bags", "--roast-id", &roast_id],
|
&["bag", "list", "--roast-id", &roast_id],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -133,14 +141,14 @@ fn test_list_bags_without_roast_id_shows_all_bags() {
|
||||||
let roast_id = create_roast(&roaster_id, "Bag List All Roast", &token);
|
let roast_id = create_roast(&roaster_id, "Bag List All Roast", &token);
|
||||||
|
|
||||||
let bag_output = run_brewlog(
|
let bag_output = run_brewlog(
|
||||||
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
|
&["bag", "add", "--roast-id", &roast_id, "--amount", "250.0"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
||||||
let bag_id = bag["id"].as_i64().unwrap();
|
let bag_id = bag["id"].as_i64().unwrap();
|
||||||
|
|
||||||
// Test: List Bags (Authenticated)
|
// Test: List Bags (Authenticated)
|
||||||
let output = run_brewlog(&["list-bags"], &[("BREWLOG_TOKEN", &token)]);
|
let output = run_brewlog(&["bag", "list"], &[("BREWLOG_TOKEN", &token)]);
|
||||||
|
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
let bags: Value = serde_json::from_slice(&output.stdout).unwrap();
|
let bags: Value = serde_json::from_slice(&output.stdout).unwrap();
|
||||||
|
|
@ -159,7 +167,7 @@ fn test_list_bags_shows_open_and_closed_bags() {
|
||||||
|
|
||||||
// Create Open Bag
|
// Create Open Bag
|
||||||
let open_bag_output = run_brewlog(
|
let open_bag_output = run_brewlog(
|
||||||
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
|
&["bag", "add", "--roast-id", &roast_id, "--amount", "250.0"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
let open_bag: Value = serde_json::from_slice(&open_bag_output.stdout).unwrap();
|
let open_bag: Value = serde_json::from_slice(&open_bag_output.stdout).unwrap();
|
||||||
|
|
@ -167,7 +175,7 @@ fn test_list_bags_shows_open_and_closed_bags() {
|
||||||
|
|
||||||
// Create Closed Bag
|
// Create Closed Bag
|
||||||
let closed_bag_output = run_brewlog(
|
let closed_bag_output = run_brewlog(
|
||||||
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
|
&["bag", "add", "--roast-id", &roast_id, "--amount", "250.0"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
let closed_bag: Value = serde_json::from_slice(&closed_bag_output.stdout).unwrap();
|
let closed_bag: Value = serde_json::from_slice(&closed_bag_output.stdout).unwrap();
|
||||||
|
|
@ -176,7 +184,8 @@ fn test_list_bags_shows_open_and_closed_bags() {
|
||||||
// Close the second bag
|
// Close the second bag
|
||||||
let _ = run_brewlog(
|
let _ = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"update-bag",
|
"bag",
|
||||||
|
"update",
|
||||||
"--id",
|
"--id",
|
||||||
&closed_bag_id.to_string(),
|
&closed_bag_id.to_string(),
|
||||||
"--closed",
|
"--closed",
|
||||||
|
|
@ -186,7 +195,7 @@ fn test_list_bags_shows_open_and_closed_bags() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test: List Bags (Authenticated)
|
// Test: List Bags (Authenticated)
|
||||||
let output = run_brewlog(&["list-bags"], &[("BREWLOG_TOKEN", &token)]);
|
let output = run_brewlog(&["bag", "list"], &[("BREWLOG_TOKEN", &token)]);
|
||||||
|
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
let bags: Value = serde_json::from_slice(&output.stdout).unwrap();
|
let bags: Value = serde_json::from_slice(&output.stdout).unwrap();
|
||||||
|
|
@ -210,7 +219,7 @@ fn test_list_bags_shows_open_and_closed_bags() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_bag_requires_authentication() {
|
fn test_delete_bag_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
let output = run_brewlog(&["delete-bag", "--id", "123"], &[]);
|
let output = run_brewlog(&["bag", "delete", "--id", "123"], &[]);
|
||||||
assert!(!output.status.success());
|
assert!(!output.status.success());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +232,7 @@ fn test_delete_bag_with_authentication() {
|
||||||
let roast_id = create_roast(&roaster_id, "Bag Delete Roast", &token);
|
let roast_id = create_roast(&roaster_id, "Bag Delete Roast", &token);
|
||||||
|
|
||||||
let bag_output = run_brewlog(
|
let bag_output = run_brewlog(
|
||||||
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
|
&["bag", "add", "--roast-id", &roast_id, "--amount", "250.0"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
|
||||||
|
|
@ -231,12 +240,12 @@ fn test_delete_bag_with_authentication() {
|
||||||
|
|
||||||
// Test: Delete Bag
|
// Test: Delete Bag
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&["delete-bag", "--id", &bag_id],
|
&["bag", "delete", "--id", &bag_id],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
|
|
||||||
// Verify deletion
|
// Verify deletion
|
||||||
let get_output = run_brewlog(&["get-bag", "--id", &bag_id], &[]);
|
let get_output = run_brewlog(&["bag", "get", "--id", &bag_id], &[]);
|
||||||
assert!(!get_output.status.success());
|
assert!(!get_output.status.success());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ fn test_add_gear_requires_authentication() {
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -20,7 +21,7 @@ fn test_add_gear_requires_authentication() {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"add-gear without auth should fail"
|
"gear add without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,7 +31,8 @@ fn test_add_gear_with_authentication() {
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -54,11 +56,11 @@ fn test_add_gear_with_authentication() {
|
||||||
fn test_list_gear_works_without_authentication() {
|
fn test_list_gear_works_without_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["list-gear"], &[]);
|
let output = run_brewlog(&["gear", "list"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"list-gear should work without auth"
|
"gear list should work without auth"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +71,8 @@ fn test_list_gear_shows_added_gear() {
|
||||||
// Add gear
|
// Add gear
|
||||||
let add_output = run_brewlog(
|
let add_output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -82,7 +85,7 @@ fn test_list_gear_shows_added_gear() {
|
||||||
assert!(add_output.status.success());
|
assert!(add_output.status.success());
|
||||||
|
|
||||||
// List gear
|
// List gear
|
||||||
let list_output = run_brewlog(&["list-gear"], &[]);
|
let list_output = run_brewlog(&["gear", "list"], &[]);
|
||||||
assert!(list_output.status.success());
|
assert!(list_output.status.success());
|
||||||
|
|
||||||
let gear_list: Value = serde_json::from_slice(&list_output.stdout).unwrap();
|
let gear_list: Value = serde_json::from_slice(&list_output.stdout).unwrap();
|
||||||
|
|
@ -103,7 +106,8 @@ fn test_list_gear_filtered_by_category() {
|
||||||
// Add grinder
|
// Add grinder
|
||||||
run_brewlog(
|
run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -117,7 +121,8 @@ fn test_list_gear_filtered_by_category() {
|
||||||
// Add brewer
|
// Add brewer
|
||||||
run_brewlog(
|
run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"brewer",
|
"brewer",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -129,7 +134,7 @@ fn test_list_gear_filtered_by_category() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// List only grinders
|
// List only grinders
|
||||||
let output = run_brewlog(&["list-gear", "--category", "grinder"], &[]);
|
let output = run_brewlog(&["gear", "list", "--category", "grinder"], &[]);
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
|
|
||||||
let gear_list: Value = serde_json::from_slice(&output.stdout).unwrap();
|
let gear_list: Value = serde_json::from_slice(&output.stdout).unwrap();
|
||||||
|
|
@ -151,7 +156,8 @@ fn test_get_gear_by_id() {
|
||||||
// Add gear
|
// Add gear
|
||||||
let add_output = run_brewlog(
|
let add_output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -165,7 +171,7 @@ fn test_get_gear_by_id() {
|
||||||
let gear_id = gear["id"].as_i64().unwrap().to_string();
|
let gear_id = gear["id"].as_i64().unwrap().to_string();
|
||||||
|
|
||||||
// Get gear by ID
|
// Get gear by ID
|
||||||
let output = run_brewlog(&["get-gear", "--id", &gear_id], &[]);
|
let output = run_brewlog(&["gear", "get", "--id", &gear_id], &[]);
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
|
|
||||||
let retrieved_gear: Value = serde_json::from_slice(&output.stdout).unwrap();
|
let retrieved_gear: Value = serde_json::from_slice(&output.stdout).unwrap();
|
||||||
|
|
@ -177,11 +183,11 @@ fn test_get_gear_by_id() {
|
||||||
fn test_update_gear_requires_authentication() {
|
fn test_update_gear_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["update-gear", "--id", "123", "--make", "Updated"], &[]);
|
let output = run_brewlog(&["gear", "update", "--id", "123", "--make", "Updated"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"update-gear without auth should fail"
|
"gear update without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,7 +198,8 @@ fn test_update_gear_with_authentication() {
|
||||||
// Add gear
|
// Add gear
|
||||||
let add_output = run_brewlog(
|
let add_output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -207,7 +214,7 @@ fn test_update_gear_with_authentication() {
|
||||||
|
|
||||||
// Update gear
|
// Update gear
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&["update-gear", "--id", &gear_id, "--model", "Mini II"],
|
&["gear", "update", "--id", &gear_id, "--model", "Mini II"],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -221,11 +228,11 @@ fn test_update_gear_with_authentication() {
|
||||||
fn test_delete_gear_requires_authentication() {
|
fn test_delete_gear_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["delete-gear", "--id", "123"], &[]);
|
let output = run_brewlog(&["gear", "delete", "--id", "123"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"delete-gear without auth should fail"
|
"gear delete without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +243,8 @@ fn test_delete_gear_with_authentication() {
|
||||||
// Add gear
|
// Add gear
|
||||||
let add_output = run_brewlog(
|
let add_output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-gear",
|
"gear",
|
||||||
|
"add",
|
||||||
"--category",
|
"--category",
|
||||||
"grinder",
|
"grinder",
|
||||||
"--make",
|
"--make",
|
||||||
|
|
@ -251,12 +259,12 @@ fn test_delete_gear_with_authentication() {
|
||||||
|
|
||||||
// Delete gear
|
// Delete gear
|
||||||
let delete_output = run_brewlog(
|
let delete_output = run_brewlog(
|
||||||
&["delete-gear", "--id", &gear_id],
|
&["gear", "delete", "--id", &gear_id],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
assert!(delete_output.status.success());
|
assert!(delete_output.status.success());
|
||||||
|
|
||||||
// Verify deletion - get should fail
|
// Verify deletion - get should fail
|
||||||
let get_output = run_brewlog(&["get-gear", "--id", &gear_id], &[]);
|
let get_output = run_brewlog(&["gear", "get", "--id", &gear_id], &[]);
|
||||||
assert!(!get_output.status.success());
|
assert!(!get_output.status.success());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,8 @@ pub fn create_token(name: &str) -> String {
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"create-token",
|
"token",
|
||||||
|
"create",
|
||||||
"--name",
|
"--name",
|
||||||
name,
|
name,
|
||||||
"--username",
|
"--username",
|
||||||
|
|
@ -165,7 +166,7 @@ pub fn run_brewlog(args: &[&str], env: &[(&str, &str)]) -> std::process::Output
|
||||||
/// Helper to create a roaster and return its ID
|
/// Helper to create a roaster and return its ID
|
||||||
pub fn create_roaster(name: &str, token: &str) -> String {
|
pub fn create_roaster(name: &str, token: &str) -> String {
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&["add-roaster", "--name", name, "--country", "UK"],
|
&["roaster", "add", "--name", name, "--country", "UK"],
|
||||||
&[("BREWLOG_TOKEN", token)],
|
&[("BREWLOG_TOKEN", token)],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -189,7 +190,8 @@ pub fn create_roaster(name: &str, token: &str) -> String {
|
||||||
pub fn create_roast(roaster_id: &str, name: &str, token: &str) -> String {
|
pub fn create_roast(roaster_id: &str, name: &str, token: &str) -> String {
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-roast",
|
"roast",
|
||||||
|
"add",
|
||||||
"--roaster-id",
|
"--roaster-id",
|
||||||
roaster_id,
|
roaster_id,
|
||||||
"--name",
|
"--name",
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,20 @@ fn test_add_roaster_requires_authentication() {
|
||||||
let _ = server_info(); // Ensure server is started
|
let _ = server_info(); // Ensure server is started
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&["add-roaster", "--name", "Test Roasters", "--country", "UK"],
|
&[
|
||||||
|
"roaster",
|
||||||
|
"add",
|
||||||
|
"--name",
|
||||||
|
"Test Roasters",
|
||||||
|
"--country",
|
||||||
|
"UK",
|
||||||
|
],
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"add-roaster without auth should fail"
|
"roaster add without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,13 +28,20 @@ fn test_add_roaster_with_authentication() {
|
||||||
let token = create_token("test-add-roaster");
|
let token = create_token("test-add-roaster");
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&["add-roaster", "--name", "Test Roasters", "--country", "UK"],
|
&[
|
||||||
|
"roaster",
|
||||||
|
"add",
|
||||||
|
"--name",
|
||||||
|
"Test Roasters",
|
||||||
|
"--country",
|
||||||
|
"UK",
|
||||||
|
],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"add-roaster with auth should succeed: {}",
|
"roaster add with auth should succeed: {}",
|
||||||
String::from_utf8_lossy(&output.stderr)
|
String::from_utf8_lossy(&output.stderr)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -44,11 +58,11 @@ fn test_add_roaster_with_authentication() {
|
||||||
fn test_list_roasters_works_without_authentication() {
|
fn test_list_roasters_works_without_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["list-roasters"], &[]);
|
let output = run_brewlog(&["roaster", "list"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"list-roasters should work without auth"
|
"roaster list should work without auth"
|
||||||
);
|
);
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
@ -65,7 +79,7 @@ fn test_list_roasters_shows_added_roaster() {
|
||||||
let roaster_id = create_roaster("Example Roasters", &token);
|
let roaster_id = create_roaster("Example Roasters", &token);
|
||||||
|
|
||||||
// List roasters
|
// List roasters
|
||||||
let list_output = run_brewlog(&["list-roasters"], &[]);
|
let list_output = run_brewlog(&["roaster", "list"], &[]);
|
||||||
|
|
||||||
assert!(list_output.status.success());
|
assert!(list_output.status.success());
|
||||||
|
|
||||||
|
|
@ -87,11 +101,11 @@ fn test_list_roasters_shows_added_roaster() {
|
||||||
fn test_delete_roaster_requires_authentication() {
|
fn test_delete_roaster_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["delete-roaster", "--id", "some-id"], &[]);
|
let output = run_brewlog(&["roaster", "delete", "--id", "some-id"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"delete-roaster without auth should fail"
|
"roaster delete without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +115,8 @@ fn test_update_roaster_requires_authentication() {
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"update-roaster",
|
"roaster",
|
||||||
|
"update",
|
||||||
"--id",
|
"--id",
|
||||||
"some-id",
|
"some-id",
|
||||||
"--name",
|
"--name",
|
||||||
|
|
@ -112,6 +127,6 @@ fn test_update_roaster_requires_authentication() {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"update-roaster without auth should fail"
|
"roaster update without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ fn test_add_roast_requires_authentication() {
|
||||||
|
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-roast",
|
"roast",
|
||||||
|
"add",
|
||||||
"--roaster-id",
|
"--roaster-id",
|
||||||
"some-id",
|
"some-id",
|
||||||
"--name",
|
"--name",
|
||||||
|
|
@ -26,7 +27,7 @@ fn test_add_roast_requires_authentication() {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"add-roast without auth should fail"
|
"roast add without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,7 +41,8 @@ fn test_add_roast_with_authentication() {
|
||||||
// Now add a roast
|
// Now add a roast
|
||||||
let output = run_brewlog(
|
let output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-roast",
|
"roast",
|
||||||
|
"add",
|
||||||
"--roaster-id",
|
"--roaster-id",
|
||||||
&roaster_id,
|
&roaster_id,
|
||||||
"--name",
|
"--name",
|
||||||
|
|
@ -61,7 +63,7 @@ fn test_add_roast_with_authentication() {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"add-roast with auth should succeed: {}",
|
"roast add with auth should succeed: {}",
|
||||||
String::from_utf8_lossy(&output.stderr)
|
String::from_utf8_lossy(&output.stderr)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -80,11 +82,11 @@ fn test_add_roast_with_authentication() {
|
||||||
fn test_list_roasts_works_without_authentication() {
|
fn test_list_roasts_works_without_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["list-roasts"], &[]);
|
let output = run_brewlog(&["roast", "list"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"list-roasts should work without auth"
|
"roast list should work without auth"
|
||||||
);
|
);
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
@ -103,7 +105,8 @@ fn test_list_roasts_shows_added_roast() {
|
||||||
// Add a roast
|
// Add a roast
|
||||||
let add_output = run_brewlog(
|
let add_output = run_brewlog(
|
||||||
&[
|
&[
|
||||||
"add-roast",
|
"roast",
|
||||||
|
"add",
|
||||||
"--roaster-id",
|
"--roaster-id",
|
||||||
&roaster_id,
|
&roaster_id,
|
||||||
"--name",
|
"--name",
|
||||||
|
|
@ -131,7 +134,7 @@ fn test_list_roasts_shows_added_roast() {
|
||||||
.expect("roast id should be numeric");
|
.expect("roast id should be numeric");
|
||||||
|
|
||||||
// List roasts
|
// List roasts
|
||||||
let list_output = run_brewlog(&["list-roasts"], &[]);
|
let list_output = run_brewlog(&["roast", "list"], &[]);
|
||||||
|
|
||||||
assert!(list_output.status.success());
|
assert!(list_output.status.success());
|
||||||
|
|
||||||
|
|
@ -157,10 +160,10 @@ fn test_list_roasts_shows_added_roast() {
|
||||||
fn test_delete_roast_requires_authentication() {
|
fn test_delete_roast_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["delete-roast", "--id", "some-id"], &[]);
|
let output = run_brewlog(&["roast", "delete", "--id", "some-id"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"delete-roast without auth should fail"
|
"roast delete without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ use crate::helpers::{create_token, run_brewlog, server_info};
|
||||||
fn test_list_tokens_requires_authentication() {
|
fn test_list_tokens_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["list-tokens"], &[]);
|
let output = run_brewlog(&["token", "list"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"list-tokens without auth should fail"
|
"token list without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16,11 +16,11 @@ fn test_list_tokens_requires_authentication() {
|
||||||
fn test_list_tokens_with_authentication() {
|
fn test_list_tokens_with_authentication() {
|
||||||
let token = create_token("test-list-tokens");
|
let token = create_token("test-list-tokens");
|
||||||
|
|
||||||
let output = run_brewlog(&["list-tokens"], &[("BREWLOG_TOKEN", &token)]);
|
let output = run_brewlog(&["token", "list"], &[("BREWLOG_TOKEN", &token)]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"list-tokens with auth should succeed"
|
"token list with auth should succeed"
|
||||||
);
|
);
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
@ -34,11 +34,11 @@ fn test_list_tokens_with_authentication() {
|
||||||
fn test_revoke_token_requires_authentication() {
|
fn test_revoke_token_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
||||||
let output = run_brewlog(&["revoke-token", "--id", "1"], &[]);
|
let output = run_brewlog(&["token", "revoke", "--id", "1"], &[]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!output.status.success(),
|
!output.status.success(),
|
||||||
"revoke-token without auth should fail"
|
"token revoke without auth should fail"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ fn test_revoke_token_with_authentication() {
|
||||||
let token = create_token("test-revoke-token");
|
let token = create_token("test-revoke-token");
|
||||||
|
|
||||||
// List tokens to get the ID
|
// List tokens to get the ID
|
||||||
let list_output = run_brewlog(&["list-tokens"], &[("BREWLOG_TOKEN", &token)]);
|
let list_output = run_brewlog(&["token", "list"], &[("BREWLOG_TOKEN", &token)]);
|
||||||
assert!(list_output.status.success());
|
assert!(list_output.status.success());
|
||||||
|
|
||||||
let list_stdout = String::from_utf8_lossy(&list_output.stdout);
|
let list_stdout = String::from_utf8_lossy(&list_output.stdout);
|
||||||
|
|
@ -66,7 +66,7 @@ fn test_revoke_token_with_authentication() {
|
||||||
.expect("Token should have ID");
|
.expect("Token should have ID");
|
||||||
|
|
||||||
let revoke_output = run_brewlog(
|
let revoke_output = run_brewlog(
|
||||||
&["revoke-token", "--id", &token_id.to_string()],
|
&["token", "revoke", "--id", &token_id.to_string()],
|
||||||
&[("BREWLOG_TOKEN", &token)],
|
&[("BREWLOG_TOKEN", &token)],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ fn test_revoked_token_cannot_be_used() {
|
||||||
let admin_token = create_token("test-admin-token");
|
let admin_token = create_token("test-admin-token");
|
||||||
|
|
||||||
// List tokens to get the ID of the token we want to revoke
|
// List tokens to get the ID of the token we want to revoke
|
||||||
let list_output = run_brewlog(&["list-tokens"], &[("BREWLOG_TOKEN", &admin_token)]);
|
let list_output = run_brewlog(&["token", "list"], &[("BREWLOG_TOKEN", &admin_token)]);
|
||||||
assert!(list_output.status.success());
|
assert!(list_output.status.success());
|
||||||
|
|
||||||
let list_stdout = String::from_utf8_lossy(&list_output.stdout);
|
let list_stdout = String::from_utf8_lossy(&list_output.stdout);
|
||||||
|
|
@ -105,7 +105,7 @@ fn test_revoked_token_cannot_be_used() {
|
||||||
|
|
||||||
// Revoke the token
|
// Revoke the token
|
||||||
let revoke_output = run_brewlog(
|
let revoke_output = run_brewlog(
|
||||||
&["revoke-token", "--id", &token_id.to_string()],
|
&["token", "revoke", "--id", &token_id.to_string()],
|
||||||
&[("BREWLOG_TOKEN", &admin_token)],
|
&[("BREWLOG_TOKEN", &admin_token)],
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
@ -115,7 +115,7 @@ fn test_revoked_token_cannot_be_used() {
|
||||||
|
|
||||||
// Try to use the revoked token - it should fail
|
// Try to use the revoked token - it should fail
|
||||||
let list_with_revoked_output =
|
let list_with_revoked_output =
|
||||||
run_brewlog(&["list-tokens"], &[("BREWLOG_TOKEN", &token_to_revoke)]);
|
run_brewlog(&["token", "list"], &[("BREWLOG_TOKEN", &token_to_revoke)]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!list_with_revoked_output.status.success(),
|
!list_with_revoked_output.status.success(),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue