cli

Command-line interface for Radroots
git clone https://radroots.dev/git/cli.git
Log | Files | Refs | README | LICENSE

commit 693e8e0d23442b57467736c0610f6f700df30ff5
parent ba0ce9d3cb1ed6a768540f16016040fd78f4c041
Author: triesap <tyson@radroots.org>
Date:   Mon, 27 Apr 2026 06:35:28 +0000

cli: make seller flow executable

- document seller setup through local account and farm defaults
- wire farm create target inputs used by seller examples
- replace weak seller example data with valid listing values
- assert validate dry-run and signed publish in seller flow tests

Diffstat:
Msrc/operation_adapter.rs | 24+++++++++++++++++++++++-
Msrc/target_cli.rs | 32++++++++++++++++++++++++++++++--
Mtests/target_cli.rs | 56++++++++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 103 insertions(+), 9 deletions(-)

diff --git a/src/operation_adapter.rs b/src/operation_adapter.rs @@ -775,7 +775,7 @@ fn value_to_data(value: Value) -> OperationData { fn target_operation_input(command: &crate::target_cli::TargetCommand) -> OperationData { use crate::target_cli::{ AccountCommand, AccountSelectionCommand, BasketCommand, BasketItemCommand, - BasketQuoteCommand, ListingCommand, MarketCommand, MarketListingCommand, + BasketQuoteCommand, FarmCommand, ListingCommand, MarketCommand, MarketListingCommand, MarketProductCommand, OrderCommand, OrderEventCommand, TargetCommand, }; @@ -798,6 +798,28 @@ fn target_operation_input(command: &crate::target_cli::TargetCommand) -> Operati }, AccountCommand::Create | AccountCommand::List => {} }, + TargetCommand::Farm(args) => match &args.command { + FarmCommand::Create(args) => { + insert_string(&mut input, "farm_d_tag", &args.farm_d_tag); + insert_string(&mut input, "name", &args.name); + insert_string(&mut input, "display_name", &args.display_name); + insert_string(&mut input, "about", &args.about); + insert_string(&mut input, "website", &args.website); + insert_string(&mut input, "picture", &args.picture); + insert_string(&mut input, "banner", &args.banner); + insert_string(&mut input, "location", &args.location); + insert_string(&mut input, "city", &args.city); + insert_string(&mut input, "region", &args.region); + insert_string(&mut input, "country", &args.country); + insert_string(&mut input, "delivery_method", &args.delivery_method); + } + FarmCommand::Get + | FarmCommand::Profile(_) + | FarmCommand::Location(_) + | FarmCommand::Fulfillment(_) + | FarmCommand::Readiness(_) + | FarmCommand::Publish => {} + }, TargetCommand::Listing(args) => match &args.command { ListingCommand::Create(args) => { insert_path(&mut input, "output", &args.output); diff --git a/src/target_cli.rs b/src/target_cli.rs @@ -141,7 +141,7 @@ impl TargetCommand { JobCommand::Watch => "job.watch", }, Self::Farm(args) => match &args.command { - FarmCommand::Create => "farm.create", + FarmCommand::Create(_) => "farm.create", FarmCommand::Get => "farm.get", FarmCommand::Profile(profile) => match profile.command { FarmProfileCommand::Update => "farm.profile.update", @@ -469,7 +469,7 @@ pub struct FarmArgs { #[derive(Debug, Clone, Subcommand)] pub enum FarmCommand { - Create, + Create(FarmCreateArgs), Get, Profile(FarmProfileArgs), Location(FarmLocationArgs), @@ -479,6 +479,34 @@ pub enum FarmCommand { } #[derive(Debug, Clone, Args)] +pub struct FarmCreateArgs { + #[arg(long = "farm-d-tag")] + pub farm_d_tag: Option<String>, + #[arg(long)] + pub name: Option<String>, + #[arg(long = "display-name")] + pub display_name: Option<String>, + #[arg(long)] + pub about: Option<String>, + #[arg(long)] + pub website: Option<String>, + #[arg(long)] + pub picture: Option<String>, + #[arg(long)] + pub banner: Option<String>, + #[arg(long)] + pub location: Option<String>, + #[arg(long)] + pub city: Option<String>, + #[arg(long)] + pub region: Option<String>, + #[arg(long)] + pub country: Option<String>, + #[arg(long = "delivery-method")] + pub delivery_method: Option<String>, +} + +#[derive(Debug, Clone, Args)] pub struct FarmProfileArgs { #[command(subcommand)] pub command: FarmProfileCommand, diff --git a/tests/target_cli.rs b/tests/target_cli.rs @@ -302,6 +302,28 @@ fn seller_mvp_flow_acceptance_uses_target_operations() { let listing_file = sandbox.root().join("listing.toml"); let listing_file = listing_file.to_string_lossy().into_owned(); + let account = json_success(&sandbox, &["--format", "json", "account", "create"]); + assert_eq!(account["operation_id"], "account.create"); + assert_eq!(account["result"]["account"]["signer"], "local"); + + let farm = json_success( + &sandbox, + &[ + "--format", + "json", + "farm", + "create", + "--name", + "Green Farm", + "--location", + "farmstand", + "--delivery-method", + "pickup", + ], + ); + assert_eq!(farm["operation_id"], "farm.create"); + assert_eq!(farm["result"]["state"], "saved"); + let create = json_success( &sandbox, &[ @@ -315,12 +337,16 @@ fn seller_mvp_flow_acceptance_uses_target_operations() { "eggs", "--title", "Eggs", + "--category", + "eggs", + "--summary", + "Fresh eggs", "--bin-id", "bin-1", "--quantity-amount", "1", "--quantity-unit", - "dozen", + "each", "--price-amount", "6", "--price-currency", @@ -328,7 +354,7 @@ fn seller_mvp_flow_acceptance_uses_target_operations() { "--price-per-amount", "1", "--price-per-unit", - "dozen", + "each", "--available", "10", ], @@ -347,7 +373,8 @@ fn seller_mvp_flow_acceptance_uses_target_operations() { ], ); assert_eq!(validate["operation_id"], "listing.validate"); - assert!(validate["result"]["valid"].is_boolean()); + assert_eq!(validate["result"]["valid"], true); + assert_eq!(validate["result"]["issues"], Value::Null); let publish = json_success( &sandbox, @@ -363,7 +390,24 @@ fn seller_mvp_flow_acceptance_uses_target_operations() { assert_eq!(publish["operation_id"], "listing.publish"); assert_eq!(publish["result"]["state"], "dry_run"); - let orders = json_success(&sandbox, &["--format", "json", "order", "list"]); - assert_eq!(orders["operation_id"], "order.list"); - assert_eq!(orders["errors"].as_array().expect("errors").len(), 0); + let signed = json_success( + &sandbox, + &[ + "--format", + "json", + "--approval-token", + "approve", + "listing", + "publish", + listing_file.as_str(), + ], + ); + assert_eq!(signed["operation_id"], "listing.publish"); + assert_eq!(signed["result"]["state"], "signed"); + assert_eq!(signed["result"]["signer_mode"], "local"); + assert_eq!( + signed["result"]["event"]["author"], + signed["result"]["seller_pubkey"] + ); + assert!(signed["result"]["event"]["signature"].is_string()); }