Skip to content

feat: product list -i, a picker over the product list - #42

Merged
alukach merged 3 commits into
feat/product-commandsfrom
feat/product-browse
Oct 13, 2026
Merged

alukach merged 3 commits into
feat/product-commandsfrom
feat/product-browse

Conversation

@alukach

@alukach alukach commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #24 (feat/product-commands). Retarget to main once #24 merges.

What

source-coop product list [ACCOUNT] [-q TEXT] [--tags …] [--featured] -i is a lightweight interactive way to click through products, without a full-screen TUI. -i is the one way in: no separate command. It refuses the printing-only flags (--json, --format, -L, --cursor), and the picker loop is plain enough to reuse if other commands get -i.

  • Picker: products appear as ACCOUNT/PRODUCT Title in a type-to-filter list (dialoguer's FuzzySelect). It ends with Load more… while the listing has more pages, which fetches 50 at a time, and Quit.
  • Product menu: a picked product is shown exactly as product view shows it, followed by Back, Open in browser, Edit and Delete.
    • Edit and Delete call the same edit and delete functions as the commands, so their prompts, re-asking on field errors and the typed-name delete confirmation all come for free. There's no second implementation.
    • After an edit, the product is fetched again and the list shows it as it now is. After a delete, it's removed from the list, and the cursor moves to the product after it.
    • A failed action, such as a 401 or a validation error, is printed and the menu is offered again; it doesn't end the session.
  • Without a terminal it refuses and points to product list.

How

  • list and list -i share one flattened Filters struct (account, -q, --tags, --featured, and the URL built from them) and one fetch_page helper, so the flags and the paging aren't duplicated.
  • Prompter gains fuzzy_select, which defaults to select. Only the terminal implementation overrides it, so the scripted test prompter works unchanged.
  • No new dependencies: this enables dialoguer's fuzzy-select feature.

Testing

  • list_i_takes_filters_but_not_printing_flags checks the flag parses with filters and clashes with the printing flags.
  • New scripted test list_i_loads_more_deletes_through_the_menu_and_quits against wiremock covers load more, picking a product, deleting it through the menu (keep data: no; typed confirmation), seeing it gone with the cursor on the next product, and quitting. It checks every list and menu offered.
  • cargo fmt, cargo clippy --all-targets -- -D warnings, cargo test and cargo test --features staging: 68 passed, on top of feat: add product commands and a gh-style api command #24's draft-saving commit (e96b301). Editing from the picker now makes feat: add product commands and a gh-style api command #24's sign-in check (GET /whoami) first.
  • Not yet tried by hand in a terminal.

🤖 Generated with Claude Code

@claude

claude Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Claude finished @alukach's task in 16s —— View job


✅ No blocking issues — safe to merge.

Reviewed git diff origin/feat/product-commands...HEAD. I didn't build or run anything, so the 63 passing tests are as reported in the PR description. The paging, cursor handling and delete flow look right.

Non-blocking notes:

  • PR description is stale. It describes product browse, but the code is product list -i (commits 9610c68 and 71c3dd0). The test is also named list_i_loads_more_…, not browse_…. Update the description before merging.
  • Edit refetch breaks the "failure doesn't end the session" promise. In src/product.rs, product_menu handles the edit with Ok(()) => product = client.get(product_url(client, &p)).await?. If that refetch fails (network blip, 401), the ? aborts the whole picker instead of printing the error and re-offering the menu. The delete and edit arms already use Err(e) => eprintln!(...), so this one is inconsistent. Suggested fix:
    Ok(()) => match client.get(product_url(client, &p)).await {
        Ok(fresh) => product = fresh,
        Err(e) => eprintln!("Error: {e}"),
    },
  • Filtering hides "Load more…". FuzzySelect filters every item, so while someone is typing a filter the "Load more…" and "Quit" entries disappear. Products that aren't loaded yet can't be matched, and the user has to clear the filter to fetch more. This is acceptable for a first version, but worth a line in the help text or README.

Simplify (ponytail)

  • src/product.rs, fetch_page: Ok(client.get(url).await?) can be client.get(url).await, if client.get already returns Result<_, String>. If it returns another error type, keep the ?.
  • src/product.rs, product_menu: EditArgs and DeleteArgs are built out with every field spelled out. If they derive Default, ..Default::default() would shorten both. Skip this if deriving it would be speculative.

💰 Estimated review cost: $0.11 · 0m16s · 4 turns

alukach and others added 3 commits October 13, 2026 16:35
browse lists products in a type-to-filter picker (dialoguer's
FuzzySelect), with "Load more…" while the listing has pages left. A
picked product is shown as view shows it, with Back, Open in browser,
Edit and Delete, which run the same code as those commands; a failed
action is reported and the menu offered again.

list and browse share their filters (account, -q, --tags, --featured)
through a flattened Filters struct, and one page fetch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One way to the picker: -i on list takes the same filters and refuses the
printing-only flags (--json, --format, -L, --cursor).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alukach
alukach force-pushed the feat/product-browse branch from 307d4ac to 71c3dd0 Compare October 13, 2026 23:36
@alukach alukach changed the title feat: product browse, a picker over the product list feat: product list -i, a picker over the product list Oct 13, 2026
@alukach
alukach marked this pull request as ready for review October 13, 2026 23:46
@alukach
alukach merged commit 23697e2 into feat/product-commands Oct 13, 2026
10 checks passed
@alukach
alukach deleted the feat/product-browse branch October 13, 2026 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant