rdapper 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,6 +53,15 @@ toRegistrableDomain("192.168.0.1"); // => null
53
53
  - `isRegistered(domain, options?) => Promise<boolean>`
54
54
  - `isAvailable(domain, options?) => Promise<boolean>`
55
55
 
56
+ ### CLI
57
+
58
+ For quick checks, a minimal CLI is included:
59
+
60
+ ```bash
61
+ npx rdapper example.com
62
+ echo "example.com" | npx rdapper
63
+ ```
64
+
56
65
  ### Edge runtimes (e.g., Vercel Edge)
57
66
 
58
67
  WHOIS requires a raw TCP connection over port 43 via `node:net`, which is not available on edge runtimes. This package lazily loads `node:net` only when the WHOIS code path runs. To use rdapper safely on edge:
@@ -196,7 +205,7 @@ Project layout:
196
205
  - `src/whois/` – WHOIS TCP client, discovery/referral, normalization, exceptions
197
206
  - `src/lib/` – utilities for dates, text parsing, domain processing, async
198
207
  - `src/types.ts` – public types; `src/index.ts` re‑exports API and types
199
- - `cli.mjs` – local CLI helper for quick testing
208
+ - `bin/cli.js` – simple CLI for quick checks
200
209
 
201
210
  ## Caveats
202
211
 
package/bin/cli.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Quick informal command-line interface for rdapper
4
+ // Usage:
5
+ // npx rdapper example.com
6
+ // echo "example.com" | npx rdapper
7
+
8
+ import { createInterface } from "node:readline";
9
+ import { lookupDomain } from "../dist/index.js";
10
+
11
+ async function main() {
12
+ if (process.argv.length > 2) {
13
+ // URL(s) specified in the command arguments
14
+ console.log(
15
+ JSON.stringify(
16
+ await lookupDomain(process.argv[process.argv.length - 1]),
17
+ null,
18
+ 2,
19
+ ),
20
+ );
21
+ } else {
22
+ // No domain passed as argument, read from each line of stdin
23
+ const rlInterface = createInterface({
24
+ input: process.stdin,
25
+ });
26
+ rlInterface.on("line", async (line) => {
27
+ console.log(JSON.stringify(await lookupDomain(line), null, 2));
28
+ });
29
+ }
30
+ }
31
+
32
+ main();
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { parse } from "tldts";
2
+
1
3
  //#region src/types.d.ts
2
4
  type LookupSource = "rdap" | "whois";
3
5
  interface RegistrarInfo {
@@ -125,11 +127,23 @@ interface LookupResult {
125
127
  type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
126
128
  //#endregion
127
129
  //#region src/lib/domain.d.ts
130
+ type ParseOptions = Parameters<typeof parse>[1];
131
+ /**
132
+ * Parse a domain into its parts. Accepts options which are passed to tldts.parse().
133
+ * @see https://github.com/remusao/tldts/blob/master/packages/tldts-core/src/options.ts
134
+ */
135
+ declare function getDomainParts(domain: string, opts?: ParseOptions): ReturnType<typeof parse>;
136
+ /** Get the TLD (ICANN-only public suffix) of a domain. */
137
+ declare function getDomainTld(domain: string, opts?: ParseOptions): string | null;
138
+ /**
139
+ * Basic domain validity check (hostname-like), not performing DNS or RDAP.
140
+ */
141
+ declare function isLikelyDomain(value: string): boolean;
128
142
  /**
129
143
  * Normalize arbitrary input (domain or URL) to its registrable domain (eTLD+1).
130
144
  * Returns null when the input is not a valid ICANN domain (e.g., invalid TLD, IPs).
131
145
  */
132
- declare function toRegistrableDomain(input: string): string | null;
146
+ declare function toRegistrableDomain(input: string, opts?: ParseOptions): string | null;
133
147
  //#endregion
134
148
  //#region src/index.d.ts
135
149
  /**
@@ -144,4 +158,4 @@ declare function isAvailable(domain: string, opts?: LookupOptions): Promise<bool
144
158
  * Performs a lookup and resolves to a boolean. Rejects on lookup error. */
145
159
  declare function isRegistered(domain: string, opts?: LookupOptions): Promise<boolean>;
146
160
  //#endregion
147
- export { Contact, DomainRecord, FetchLike, LookupOptions, LookupResult, LookupSource, Nameserver, RegistrarInfo, StatusEvent, isAvailable, isRegistered, lookupDomain, toRegistrableDomain };
161
+ export { Contact, DomainRecord, FetchLike, LookupOptions, LookupResult, LookupSource, Nameserver, RegistrarInfo, StatusEvent, getDomainParts, getDomainTld, isAvailable, isLikelyDomain, isRegistered, lookupDomain, toRegistrableDomain };
package/dist/index.js CHANGED
@@ -2,10 +2,18 @@ import { parse } from "tldts";
2
2
 
3
3
  //#region src/lib/domain.ts
4
4
  /**
5
- * Parse a domain into its parts.
5
+ * Parse a domain into its parts. Accepts options which are passed to tldts.parse().
6
+ * @see https://github.com/remusao/tldts/blob/master/packages/tldts-core/src/options.ts
6
7
  */
7
- function getDomainParts(domain) {
8
- return parse(domain);
8
+ function getDomainParts(domain, opts) {
9
+ return parse(domain, { ...opts });
10
+ }
11
+ /** Get the TLD (ICANN-only public suffix) of a domain. */
12
+ function getDomainTld(domain, opts) {
13
+ return getDomainParts(domain, {
14
+ allowPrivateDomains: false,
15
+ ...opts
16
+ }).publicSuffix ?? null;
9
17
  }
10
18
  /**
11
19
  * Basic domain validity check (hostname-like), not performing DNS or RDAP.
@@ -18,10 +26,13 @@ function isLikelyDomain(value) {
18
26
  * Normalize arbitrary input (domain or URL) to its registrable domain (eTLD+1).
19
27
  * Returns null when the input is not a valid ICANN domain (e.g., invalid TLD, IPs).
20
28
  */
21
- function toRegistrableDomain(input) {
29
+ function toRegistrableDomain(input, opts) {
22
30
  const raw = (input ?? "").trim();
23
31
  if (raw === "") return null;
24
- const result = parse(raw);
32
+ const result = getDomainParts(raw, {
33
+ allowPrivateDomains: false,
34
+ ...opts
35
+ });
25
36
  if (result.isIp) return null;
26
37
  if (!result.isIcann) return null;
27
38
  const domain = result.domain ?? "";
@@ -966,7 +977,11 @@ async function followWhoisReferrals(initialServer, domain, opts) {
966
977
  if (visited.has(normalized)) break;
967
978
  visited.add(normalized);
968
979
  try {
969
- current = await whoisQuery(next, domain, opts);
980
+ const res = await whoisQuery(next, domain, opts);
981
+ const registeredBefore = !isWhoisAvailable(current.text);
982
+ const registeredAfter = !isWhoisAvailable(res.text);
983
+ if (registeredBefore && !registeredAfter) break;
984
+ current = res;
970
985
  } catch {
971
986
  break;
972
987
  }
@@ -1052,4 +1067,4 @@ async function isRegistered(domain, opts) {
1052
1067
  }
1053
1068
 
1054
1069
  //#endregion
1055
- export { isAvailable, isRegistered, lookupDomain, toRegistrableDomain };
1070
+ export { getDomainParts, getDomainTld, isAvailable, isLikelyDomain, isRegistered, lookupDomain, toRegistrableDomain };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rdapper",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "description": "🎩 RDAP/WHOIS fetcher, parser, and normalizer for Node",
6
6
  "repository": {
@@ -15,15 +15,19 @@
15
15
  "email": "jake@jarv.is",
16
16
  "url": "https://jarv.is"
17
17
  },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
18
21
  "type": "module",
19
22
  "main": "./dist/index.js",
20
23
  "module": "./dist/index.js",
21
24
  "types": "./dist/index.d.ts",
25
+ "bin": "./bin/cli.js",
22
26
  "exports": {
23
27
  ".": {
24
- "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js",
25
29
  "import": "./dist/index.js",
26
- "default": "./dist/index.js"
30
+ "types": "./dist/index.d.ts"
27
31
  }
28
32
  },
29
33
  "files": [
@@ -32,6 +36,7 @@
32
36
  "scripts": {
33
37
  "build": "tsdown",
34
38
  "dev": "tsdown --watch",
39
+ "cli": "node bin/cli.js",
35
40
  "typecheck": "tsc --noEmit",
36
41
  "test": "vitest",
37
42
  "test:run": "vitest run",
@@ -42,9 +47,9 @@
42
47
  "tldts": "7.0.17"
43
48
  },
44
49
  "devDependencies": {
45
- "@biomejs/biome": "2.2.5",
46
- "@types/node": "24.7.2",
47
- "tsdown": "0.15.6",
50
+ "@biomejs/biome": "2.2.6",
51
+ "@types/node": "24.8.1",
52
+ "tsdown": "0.15.7",
48
53
  "typescript": "5.9.3",
49
54
  "vitest": "^3.2.4"
50
55
  },