Skip to content

Commit b3adbf8

Browse files
committed
Rename lookupDomain() to lookup() (with backwards compatibility)
1 parent 5cbefe6 commit b3adbf8

File tree

6 files changed

+79
-58
lines changed

6 files changed

+79
-58
lines changed

README.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,14 @@ npm install rdapper
2323
## Quick Start
2424

2525
```ts
26-
import { lookupDomain } from "rdapper";
26+
import { lookup } from "rdapper";
2727

28-
const { ok, record, error } = await lookupDomain("example.com");
28+
const { ok, record, error } = await lookup("example.com");
2929

3030
if (!ok) throw new Error(error);
3131
console.log(record); // normalized DomainRecord
3232
```
3333

34-
Also available:
35-
36-
```ts
37-
import { isRegistered, isAvailable } from "rdapper";
38-
39-
await isRegistered("example.com"); // => true
40-
await isAvailable("likely-unregistered-thing-320485230458.com"); // => false
41-
```
42-
4334
Normalize arbitrary input (domain or URL) to its registrable domain (eTLD+1):
4435

4536
```ts
@@ -50,11 +41,25 @@ toRegistrableDomain("spark-public.s3.amazonaws.com"); // => "amazonaws.com" (I
5041
toRegistrableDomain("192.168.0.1"); // => null
5142
```
5243

44+
Convenience helpers to quickly check availability:
45+
46+
```ts
47+
import { isRegistered, isAvailable } from "rdapper";
48+
49+
await isRegistered("example.com"); // => true
50+
await isRegistered("likely-unregistered-thing-320485230458.com"); // => false
51+
await isAvailable("example.com"); // => false
52+
await isAvailable("likely-unregistered-thing-320485230458.com"); // => true
53+
```
54+
5355
## API
5456

55-
- `lookupDomain(domain, options?) => Promise<LookupResult>`
57+
- `lookup(domain, options?) => Promise<LookupResult>`
5658
- Tries RDAP first if supported by the domain’s TLD; if unavailable or fails, falls back to WHOIS (unless toggled off).
5759
- Result is `{ ok: boolean, record?: DomainRecord, error?: string }`.
60+
- `toRegistrableDomain(input, options?) => string | null`
61+
- Normalizes a domain or URL to its registrable domain (eTLD+1).
62+
- Returns the registrable domain string, or `null` for IPs/invalid input; [options](https://github.com/remusao/tldts/blob/master/packages/tldts-core/src/options.ts) are forwarded to `tldts` (e.g., `allowPrivateDomains`).
5863
- `isRegistered(domain, options?) => Promise<boolean>`
5964
- `isAvailable(domain, options?) => Promise<boolean>`
6065

@@ -74,9 +79,9 @@ WHOIS requires a raw TCP connection over port 43 via `node:net`, which is not av
7479
- Prefer RDAP only on edge:
7580

7681
```ts
77-
import { lookupDomain } from "rdapper";
82+
import { lookup } from "rdapper";
7883

79-
const res = await lookupDomain("example.com", { rdapOnly: true });
84+
const res = await lookup("example.com", { rdapOnly: true });
8085
```
8186

8287
- If `rdapOnly` is omitted and the code path reaches WHOIS on edge, rdapper throws a clear runtime error advising to run in Node or set `{ rdapOnly: true }`.

bin/cli.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
// echo "example.com" | npx rdapper
77

88
import { createInterface } from "node:readline";
9-
import { lookupDomain } from "../dist/index.js";
9+
import { lookup } from "../dist/index.js";
1010

1111
async function main() {
1212
if (process.argv.length > 2) {
1313
// URL(s) specified in the command arguments
1414
console.log(
1515
JSON.stringify(
16-
await lookupDomain(process.argv[process.argv.length - 1]),
16+
await lookup(process.argv[process.argv.length - 1]),
1717
null,
1818
2,
1919
),
@@ -24,7 +24,7 @@ async function main() {
2424
input: process.stdin,
2525
});
2626
rlInterface.on("line", async (line) => {
27-
console.log(JSON.stringify(await lookupDomain(line), null, 2));
27+
console.log(JSON.stringify(await lookup(line), null, 2));
2828
});
2929
}
3030
}

src/index.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
* High-level lookup that prefers RDAP and falls back to WHOIS.
2121
* Ensures a standardized DomainRecord, independent of the source.
2222
*/
23-
export async function lookupDomain(
23+
export async function lookup(
2424
domain: string,
2525
opts?: LookupOptions,
2626
): Promise<LookupResult> {
@@ -118,28 +118,37 @@ export async function lookupDomain(
118118
}
119119
}
120120

121-
/** Determine if a domain appears available (not registered).
122-
* Performs a lookup and resolves to a boolean. Rejects on lookup error. */
121+
/**
122+
* Determine if a domain appears available (not registered).
123+
* Performs a lookup and resolves to a boolean. Rejects on lookup error.
124+
*/
123125
export async function isAvailable(
124126
domain: string,
125127
opts?: LookupOptions,
126128
): Promise<boolean> {
127-
const res = await lookupDomain(domain, opts);
129+
const res = await lookup(domain, opts);
128130
if (!res.ok || !res.record) throw new Error(res.error || "Lookup failed");
129131
return res.record.isRegistered === false;
130132
}
131133

132-
/** Determine if a domain appears registered.
133-
* Performs a lookup and resolves to a boolean. Rejects on lookup error. */
134+
/**
135+
* Determine if a domain appears registered.
136+
* Performs a lookup and resolves to a boolean. Rejects on lookup error.
137+
*/
134138
export async function isRegistered(
135139
domain: string,
136140
opts?: LookupOptions,
137141
): Promise<boolean> {
138-
const res = await lookupDomain(domain, opts);
142+
const res = await lookup(domain, opts);
139143
if (!res.ok || !res.record) throw new Error(res.error || "Lookup failed");
140144
return res.record.isRegistered === true;
141145
}
142146

147+
/**
148+
* @deprecated Use `lookup` instead.
149+
*/
150+
export const lookupDomain = lookup;
151+
143152
export {
144153
getDomainParts,
145154
getDomainTld,

src/lib/domain.ts

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { parse } from "tldts";
33
type ParseOptions = Parameters<typeof parse>[1];
44

55
/**
6-
* Parse a domain into its parts. Accepts options which are passed to tldts.parse().
6+
* Parse a domain into its parts. Passes options to `tldts.parse()`.
77
* @see https://github.com/remusao/tldts/blob/master/packages/tldts-core/src/options.ts
88
*/
99
export function getDomainParts(
@@ -13,7 +13,10 @@ export function getDomainParts(
1313
return parse(domain, { ...opts });
1414
}
1515

16-
/** Get the TLD (ICANN-only public suffix) of a domain. */
16+
/**
17+
* Get the TLD (ICANN-only public suffix) of a domain. Passes options to `tldts.parse()`.
18+
* @see https://github.com/remusao/tldts/blob/master/packages/tldts-core/src/options.ts
19+
*/
1720
export function getDomainTld(
1821
domain: string,
1922
opts?: ParseOptions,
@@ -47,7 +50,9 @@ export function punyToUnicode(domain: string): string {
4750

4851
/**
4952
* Normalize arbitrary input (domain or URL) to its registrable domain (eTLD+1).
50-
* Returns null when the input is not a valid ICANN domain (e.g., invalid TLD, IPs).
53+
* Passes options to `tldts.parse()`.
54+
* Returns null when the input is not a valid ICANN domain (e.g., invalid TLD, IPs)
55+
* @see https://github.com/remusao/tldts/blob/master/packages/tldts-core/src/options.ts
5156
*/
5257
export function toRegistrableDomain(
5358
input: string,
@@ -69,27 +74,3 @@ export function toRegistrableDomain(
6974
if (domain === "") return null;
7075
return domain.toLowerCase();
7176
}
72-
73-
// Common WHOIS availability phrases seen across registries/registrars
74-
const WHOIS_AVAILABLE_PATTERNS: RegExp[] = [
75-
/\bno match\b/i,
76-
/\bnot found\b/i,
77-
/\bno entries found\b/i,
78-
/\bno data found\b/i,
79-
/\bavailable for registration\b/i,
80-
/\bdomain\s+available\b/i,
81-
/\bdomain status[:\s]+available\b/i,
82-
/\bobject does not exist\b/i,
83-
/\bthe queried object does not exist\b/i,
84-
// Common variants across ccTLDs/registrars
85-
/\bstatus:\s*free\b/i,
86-
/\bstatus:\s*available\b/i,
87-
/\bno object found\b/i,
88-
/\bnicht gefunden\b/i,
89-
/\bpending release\b/i, // often signals not registered/being deleted
90-
];
91-
92-
export function isWhoisAvailable(text: string | undefined): boolean {
93-
if (!text) return false;
94-
return WHOIS_AVAILABLE_PATTERNS.some((re) => re.test(text));
95-
}

src/whois/normalize.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { toISO } from "../lib/dates";
2-
import { isWhoisAvailable } from "../lib/domain";
32
import { isPrivacyName } from "../lib/privacy";
43
import { parseKeyValueLines, uniq } from "../lib/text";
54
import type {
@@ -9,6 +8,33 @@ import type {
98
RegistrarInfo,
109
} from "../types";
1110

11+
// Common WHOIS availability phrases seen across registries/registrars
12+
const WHOIS_AVAILABLE_PATTERNS: RegExp[] = [
13+
/\bno match\b/i,
14+
/\bnot found\b/i,
15+
/\bno entries found\b/i,
16+
/\bno data found\b/i,
17+
/\bavailable for registration\b/i,
18+
/\bdomain\s+available\b/i,
19+
/\bdomain status[:\s]+available\b/i,
20+
/\bobject does not exist\b/i,
21+
/\bthe queried object does not exist\b/i,
22+
// Common variants across ccTLDs/registrars
23+
/\bstatus:\s*free\b/i,
24+
/\bstatus:\s*available\b/i,
25+
/\bno object found\b/i,
26+
/\bnicht gefunden\b/i,
27+
/\bpending release\b/i, // often signals not registered/being deleted
28+
];
29+
30+
/**
31+
* Best-effort heuristic to determine if a WHOIS response indicates the domain is available.
32+
*/
33+
export function isAvailableByWhois(text: string | undefined): boolean {
34+
if (!text) return false;
35+
return WHOIS_AVAILABLE_PATTERNS.some((re) => re.test(text));
36+
}
37+
1238
/**
1339
* Convert raw WHOIS text into our normalized DomainRecord.
1440
* Heuristics cover many gTLD and ccTLD formats; exact fields vary per registry.
@@ -163,7 +189,7 @@ export function normalizeWhois(
163189
const record: DomainRecord = {
164190
domain,
165191
tld,
166-
isRegistered: !isWhoisAvailable(whoisText),
192+
isRegistered: !isAvailableByWhois(whoisText),
167193
isIDN: /(^|\.)xn--/i.test(domain),
168194
unicodeName: undefined,
169195
punycodeName: undefined,

src/whois/referral.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { isWhoisAvailable } from "../lib/domain";
21
import type { LookupOptions } from "../types";
32
import type { WhoisQueryResult } from "./client";
43
import { whoisQuery } from "./client";
54
import { extractWhoisReferral } from "./discovery";
5+
import { isAvailableByWhois } from "./normalize";
66

77
/**
88
* Follow registrar WHOIS referrals up to a configured hop limit.
@@ -30,8 +30,8 @@ export async function followWhoisReferrals(
3030
try {
3131
const res = await whoisQuery(next, domain, opts);
3232
// Prefer authoritative TLD response when registrar contradicts availability
33-
const registeredBefore = !isWhoisAvailable(current.text);
34-
const registeredAfter = !isWhoisAvailable(res.text);
33+
const registeredBefore = !isAvailableByWhois(current.text);
34+
const registeredAfter = !isAvailableByWhois(res.text);
3535
if (registeredBefore && !registeredAfter) {
3636
// Registrar claims availability but TLD shows registered: keep TLD
3737
break;
@@ -74,8 +74,8 @@ export async function collectWhoisReferralChain(
7474
try {
7575
const res = await whoisQuery(next, domain, opts);
7676
// If registrar claims availability while TLD indicated registered, stop.
77-
const registeredBefore = !isWhoisAvailable(current.text);
78-
const registeredAfter = !isWhoisAvailable(res.text);
77+
const registeredBefore = !isAvailableByWhois(current.text);
78+
const registeredAfter = !isAvailableByWhois(res.text);
7979
if (registeredBefore && !registeredAfter) {
8080
// Do not adopt or append contradictory registrar; keep authoritative TLD only.
8181
break;

0 commit comments

Comments
 (0)