From 7e2b2473e8052ff5b0d033737f7e3d2fed6c0d3a Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Sat, 3 Oct 2026 15:36:21 -0400 Subject: [PATCH] fix: make the CLI look up every argument and report failures The CLI looked up only the last argument (an option like --rdap-only was taken as the domain), always exited 0, and started every stdin line's lookup at once, so results could print out of order and many lines hit registries together. Look up each argument, or each non-blank stdin line, one at a time in order; exit 1 when any lookup fails and 2 on an unknown option. Co-Authored-By: Claude Opus 5.5 --- README.md | 4 +++- bin/cli.mjs | 36 ++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 77de38e..bc5b777 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,12 @@ await isAvailable("likely-unregistered-thing-320485230458.com"); // => true For quick checks, a minimal CLI is included: ```bash -npx rdapper example.com +npx rdapper example.com example.org echo "example.com" | npx rdapper ``` +Domains are looked up one at a time, in order, printing each result as JSON; the exit code is `1` when any lookup fails. + ### Edge runtimes (e.g., Vercel Edge) WHOIS requires a raw TCP connection over port 43 via `node:net`, which is not available on edge runtimes. rdapper lazily loads `node:net` only when the WHOIS path is taken. diff --git a/bin/cli.mjs b/bin/cli.mjs index 9a24d46..c8eabd9 100755 --- a/bin/cli.mjs +++ b/bin/cli.mjs @@ -2,24 +2,36 @@ // Quick informal command-line interface for rdapper // Usage: -// npx rdapper example.com +// npx rdapper example.com [example.org ...] // echo "example.com" | npx rdapper +// Exits with 1 when any lookup fails. import { createInterface } from "node:readline"; import { lookup } from "../dist/index.mjs"; +/** Domains from the arguments, or else one per non-blank line of stdin. */ +async function* domains() { + const args = process.argv.slice(2); + if (args.length) { + yield* args; + return; + } + for await (const line of createInterface({ input: process.stdin })) { + if (line.trim()) yield line; + } +} + async function main() { - if (process.argv.length > 2) { - // URL(s) specified in the command arguments - console.log(JSON.stringify(await lookup(process.argv[process.argv.length - 1]), null, 2)); - } else { - // No domain passed as argument, read from each line of stdin - const rlInterface = createInterface({ - input: process.stdin, - }); - rlInterface.on("line", async (line) => { - console.log(JSON.stringify(await lookup(line), null, 2)); - }); + // One at a time, so output follows input order and registries aren't flooded + for await (const domain of domains()) { + if (domain.startsWith("-")) { + console.error(`Unknown option: ${domain}`); + process.exitCode = 2; + return; + } + const result = await lookup(domain); + if (!result.ok) process.exitCode = 1; + console.log(JSON.stringify(result, null, 2)); } }