diff --git a/.changeset/fix-cli-validation.md b/.changeset/fix-cli-validation.md new file mode 100644 index 0000000..4920343 --- /dev/null +++ b/.changeset/fix-cli-validation.md @@ -0,0 +1,5 @@ +--- +"@satoshai/abi-cli": patch +--- + +Add CLI validation for --output/--stdout with multiple contracts and improve fetch error messages diff --git a/src/commands/fetch.ts b/src/commands/fetch.ts index d03a7a0..528081d 100644 --- a/src/commands/fetch.ts +++ b/src/commands/fetch.ts @@ -50,6 +50,18 @@ export const fetchCommand = defineCommand({ const contractIds = args.contract.split(',').map((s) => s.trim()); + if (args.output && contractIds.length > 1) { + throw new Error( + '--output cannot be used with multiple contracts. Omit --output to write separate files, or use --stdout.', + ); + } + + if (args.stdout && contractIds.length > 1) { + throw new Error( + '--stdout cannot be used with multiple contracts. Fetch one contract at a time with --stdout.', + ); + } + for (const contractId of contractIds) { const { address, name } = parseContractId(contractId); diff --git a/src/fetcher.ts b/src/fetcher.ts index 18a1523..18de543 100644 --- a/src/fetcher.ts +++ b/src/fetcher.ts @@ -31,7 +31,15 @@ export async function fetchContractAbi( const baseUrl = resolveNetwork(network); const url = `${baseUrl}/v2/contracts/interface/${address}/${name}`; - const response = await fetch(url); + let response: Response; + try { + response = await fetch(url); + } catch (cause) { + throw new Error( + `Network error fetching ABI for ${address}.${name} on ${network}`, + { cause }, + ); + } if (!response.ok) { if (response.status === 404) { @@ -44,5 +52,12 @@ export async function fetchContractAbi( ); } - return (await response.json()) as ClarityAbi; + try { + return (await response.json()) as ClarityAbi; + } catch (cause) { + throw new Error( + `Invalid JSON response for ${address}.${name} on ${network}`, + { cause }, + ); + } }