feat(cli)(#32): canonical UX — --json, --help, asset-pair input, auto-help on errors#33
Merged
Merged
Conversation
3 tasks
…-help on errors Issue #32 — sphere-cli UX consistency. No more legacy: every command takes the same input shape, defaults to human-friendly output, and prints the full help block (never a one-line "Usage:" stub) on errors. Five-pass implementation (legacy-cli.ts): Pass A — Output formatting - New formatOutput(payload, shape, label?) helper with a typed OutputShape union and per-shape renderers (identity, invoice-terms, invoice-status, transfer-result, swap-status, etc.). - Global --json flag (jsonMode) opts back into JSON; default is a human-readable labelled block. - Replaced 22 console.log(JSON.stringify(...)) sites in the dispatch body. File-write/POST-body JSON.stringify calls remain (wire format). Pass B — Canonical asset input - Dropped parseAssetArg (quoted compound form, "10 UCT"). - New consumeAssetPair(args, startIdx) reads two argv tokens. - invoice-create, invoice-return, swap-propose all take --asset <amount> <coin>, --offer <amount> <coin>, --want <amount> <coin>. - invoice-create now supports multiple --asset flags for multi-asset invoices. Pass C — --help works everywhere - Early-dispatch shim in main() catches --help/-h before the switch, handling sub-subcommand keys ("wallet create", "daemon start") via compound lookup with fallback to top-level. - src/index.ts: legacy subcommands disable commander's built-in --help (helpOption(false)) so the flag reaches our dispatcher. - "help" added to LEGACY_NAMESPACES so `sphere help <cmd>` routes through the COMMAND_HELP registry. - Universal flags (--json, --help/-h) added to printCommandHelp output. Pass D — Completion + docs - Added COMMAND_HELP entries for `completions` and `help` so the drift-guard test passes. - README: new "UX — canonical conventions" + "Shell completion" sections documenting the canonical syntax and three install paths (no-sudo, system-wide, per-user zsh fpath). Pass E — Auto-help on invalid input - Single failWithHelp(cmdName, errorMsg) helper prints "Error: <msg>" followed by the full COMMAND_HELP block to stderr, then exit(1). - Replaced ~40 `console.error('Usage: …'); process.exit(1)` sites. - New helper resolveInvoiceId() collapses the duplicated invoice-prefix lookup boilerplate across ~10 invoice-* commands. Plus a new src/legacy/legacy-cli-ux.test.ts that statically guards the invariants (no stray JSON.stringify, no "Usage:" stubs, no parseAssetArg calls, completion ↔ COMMAND_HELP alignment) so future drift surfaces as a test failure. Verified: typecheck clean, 113/113 tests pass (incl. 7 new UX guard tests), build clean, smoke-tested `sphere invoice create --help`, `sphere swap propose --help`, `sphere help send`, and the missing-args auto-help path on `sphere payments send`.
c2c8771 to
310c981
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #32.
Issue #32 asked for sphere-cli UX consistency across five concrete goals.
This PR delivers all five passes as a clean break — no backwards-compat
shims for the legacy quoted-asset form or for the JSON-by-default output.
What changed
Pass A — output formatting
formatOutput(payload, shape, label?)helper with a typedOutputShapeunion and per-shape renderers (identity, invoice-terms,invoice-status, transfer-result, swap-status, swap-ping, auto-return,
invoice-transfers, generic, …).
--jsonflag opts back into JSON; default is a human-readablelabelled block.
console.log(JSON.stringify(...))sites. File-write /POST-body
JSON.stringifycalls remain (wire format).Pass B — canonical asset input
parseAssetArg(quoted compound form,"10 UCT").consumeAssetPair(args, startIdx)reads two argv tokens.invoice-create,invoice-return,swap-proposenow take--asset <amount> <coin>,--offer <amount> <coin>,--want <amount> <coin>.invoice-createsupports multiple--assetflags for multi-assetinvoices.
Pass C —
--helpworks for every command/subcommandmain()catches--help/-hbefore theswitch, handling sub-subcommand keys (
wallet create,daemon start)via compound lookup with fallback to top-level.
src/index.ts: legacy subcommands disable commander's built-in--help(helpOption(false)) so the flag reaches our dispatcher.helpadded toLEGACY_NAMESPACESsosphere help <cmd>routesthrough the
COMMAND_HELPregistry.--json,--help/-h) shown in every help block.Pass D — completion + docs
COMMAND_HELPentries forcompletionsandhelpso thedrift-guard test passes.
sections documenting the canonical syntax and three install paths
(no-sudo, system-wide, per-user zsh fpath).
Pass E — auto-help on invalid input
failWithHelp(cmdName, errorMsg)helper printsError: <msg>followed by the fullCOMMAND_HELPblock to stderr,then
exit(1).console.error('Usage: …'); process.exit(1)sites.resolveInvoiceId()helper collapses the duplicatedinvoice-prefix lookup boilerplate across ~10 invoice-* commands.
Static UX guard
New
src/legacy/legacy-cli-ux.test.tsenforces the invariants sofuture drift surfaces as a test failure:
console.log(JSON.stringify(...))in the dispatch body.console.error('Usage: …'); process.exit(…)legacy stubs.parseAssetArg(...)call sites.COMMAND_HELPkey is reachable through the completion list.formatOutput,failWithHelp,consumeAssetPair) exist.--jsonand--helpshims are wired inmain().Verification
Smoke-tested in dev:
sphere invoice create --help→ prints the new canonical help blocksphere swap propose --help→ canonical--offer <amount> <coin>formsphere help send→ routes throughCOMMAND_HELP['send']sphere payments send(no args) →Error: …+ full help block + exit 1sphere wallet initintegration test compatibility: human renderkeeps
l1Address/directAddress/chainPubkeyas labels so theexisting
toMatch(/l1Address/)assertion still passes.Breaking changes (intentional — "no more legacy")
--asset "10 UCT") is no longeraccepted. Use
--asset 10 UCT(two positional tokens).CLI stdout must pass
--json.Both are explicitly called out in the new "UX — canonical conventions"
README section so the migration path is one place.
Out of scope (per the issue)
legacy-cli.tsmonolith — that's its own refactor;this PR lands within the existing file structure as the issue
permits.