domain-search-mcp 1.0.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/.env.example +52 -0
- package/Dockerfile +15 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/SECURITY.md +252 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +117 -0
- package/dist/config.js.map +1 -0
- package/dist/fallbacks/index.d.ts +6 -0
- package/dist/fallbacks/index.d.ts.map +1 -0
- package/dist/fallbacks/index.js +14 -0
- package/dist/fallbacks/index.js.map +1 -0
- package/dist/fallbacks/rdap.d.ts +18 -0
- package/dist/fallbacks/rdap.d.ts.map +1 -0
- package/dist/fallbacks/rdap.js +339 -0
- package/dist/fallbacks/rdap.js.map +1 -0
- package/dist/fallbacks/whois.d.ts +27 -0
- package/dist/fallbacks/whois.d.ts.map +1 -0
- package/dist/fallbacks/whois.js +219 -0
- package/dist/fallbacks/whois.js.map +1 -0
- package/dist/registrars/base.d.ts +89 -0
- package/dist/registrars/base.d.ts.map +1 -0
- package/dist/registrars/base.js +203 -0
- package/dist/registrars/base.js.map +1 -0
- package/dist/registrars/index.d.ts +7 -0
- package/dist/registrars/index.d.ts.map +1 -0
- package/dist/registrars/index.js +15 -0
- package/dist/registrars/index.js.map +1 -0
- package/dist/registrars/namecheap.d.ts +69 -0
- package/dist/registrars/namecheap.d.ts.map +1 -0
- package/dist/registrars/namecheap.js +307 -0
- package/dist/registrars/namecheap.js.map +1 -0
- package/dist/registrars/porkbun.d.ts +63 -0
- package/dist/registrars/porkbun.d.ts.map +1 -0
- package/dist/registrars/porkbun.js +299 -0
- package/dist/registrars/porkbun.js.map +1 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +209 -0
- package/dist/server.js.map +1 -0
- package/dist/services/domain-search.d.ts +40 -0
- package/dist/services/domain-search.d.ts.map +1 -0
- package/dist/services/domain-search.js +438 -0
- package/dist/services/domain-search.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +11 -0
- package/dist/services/index.js.map +1 -0
- package/dist/tools/bulk_search.d.ts +72 -0
- package/dist/tools/bulk_search.d.ts.map +1 -0
- package/dist/tools/bulk_search.js +108 -0
- package/dist/tools/bulk_search.js.map +1 -0
- package/dist/tools/check_socials.d.ts +71 -0
- package/dist/tools/check_socials.d.ts.map +1 -0
- package/dist/tools/check_socials.js +357 -0
- package/dist/tools/check_socials.js.map +1 -0
- package/dist/tools/compare_registrars.d.ts +80 -0
- package/dist/tools/compare_registrars.d.ts.map +1 -0
- package/dist/tools/compare_registrars.js +116 -0
- package/dist/tools/compare_registrars.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +31 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/search_domain.d.ts +61 -0
- package/dist/tools/search_domain.d.ts.map +1 -0
- package/dist/tools/search_domain.js +81 -0
- package/dist/tools/search_domain.js.map +1 -0
- package/dist/tools/suggest_domains.d.ts +82 -0
- package/dist/tools/suggest_domains.d.ts.map +1 -0
- package/dist/tools/suggest_domains.js +227 -0
- package/dist/tools/suggest_domains.js.map +1 -0
- package/dist/tools/tld_info.d.ts +56 -0
- package/dist/tools/tld_info.d.ts.map +1 -0
- package/dist/tools/tld_info.js +273 -0
- package/dist/tools/tld_info.js.map +1 -0
- package/dist/types.d.ts +193 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +81 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +192 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/errors.d.ts +87 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +191 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +24 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +27 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +132 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/premium-analyzer.d.ts +33 -0
- package/dist/utils/premium-analyzer.d.ts.map +1 -0
- package/dist/utils/premium-analyzer.js +273 -0
- package/dist/utils/premium-analyzer.js.map +1 -0
- package/dist/utils/validators.d.ts +53 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +159 -0
- package/dist/utils/validators.js.map +1 -0
- package/docs/marketing/devto-post.md +135 -0
- package/docs/marketing/hackernews.md +42 -0
- package/docs/marketing/producthunt.md +109 -0
- package/docs/marketing/reddit-post.md +59 -0
- package/docs/marketing/twitter-thread.md +105 -0
- package/examples/bulk-search-50-domains.ts +131 -0
- package/examples/cli-interactive.ts +280 -0
- package/examples/compare-registrars.ts +78 -0
- package/examples/search-single-domain.ts +54 -0
- package/examples/suggest-names.ts +110 -0
- package/glama.json +6 -0
- package/jest.config.js +35 -0
- package/package.json +62 -0
- package/smithery.yaml +36 -0
- package/src/config.ts +121 -0
- package/src/fallbacks/index.ts +6 -0
- package/src/fallbacks/rdap.ts +407 -0
- package/src/fallbacks/whois.ts +250 -0
- package/src/registrars/base.ts +264 -0
- package/src/registrars/index.ts +7 -0
- package/src/registrars/namecheap.ts +378 -0
- package/src/registrars/porkbun.ts +380 -0
- package/src/server.ts +276 -0
- package/src/services/domain-search.ts +567 -0
- package/src/services/index.ts +9 -0
- package/src/tools/bulk_search.ts +142 -0
- package/src/tools/check_socials.ts +467 -0
- package/src/tools/compare_registrars.ts +162 -0
- package/src/tools/index.ts +45 -0
- package/src/tools/search_domain.ts +93 -0
- package/src/tools/suggest_domains.ts +284 -0
- package/src/tools/tld_info.ts +294 -0
- package/src/types.ts +289 -0
- package/src/utils/cache.ts +238 -0
- package/src/utils/errors.ts +262 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/logger.ts +162 -0
- package/src/utils/premium-analyzer.ts +303 -0
- package/src/utils/validators.ts +193 -0
- package/tests/premium-analyzer.test.ts +310 -0
- package/tests/unit/cache.test.ts +123 -0
- package/tests/unit/errors.test.ts +190 -0
- package/tests/unit/tld-info.test.ts +62 -0
- package/tests/unit/tools.test.ts +200 -0
- package/tests/unit/validators.test.ts +146 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RDAP (Registration Data Access Protocol) Fallback.
|
|
4
|
+
*
|
|
5
|
+
* RFC 7480 - Modern replacement for WHOIS.
|
|
6
|
+
* Provides availability status only (no pricing).
|
|
7
|
+
* Public API - no authentication required.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.checkRdap = checkRdap;
|
|
14
|
+
exports.isRdapAvailable = isRdapAvailable;
|
|
15
|
+
const axios_1 = __importDefault(require("axios"));
|
|
16
|
+
const zod_1 = require("zod");
|
|
17
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
18
|
+
const errors_js_1 = require("../utils/errors.js");
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
20
|
+
// Zod Schemas for RDAP Response Validation (RFC 7483)
|
|
21
|
+
// SECURITY: Validate RDAP responses to prevent unexpected data
|
|
22
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
23
|
+
/**
|
|
24
|
+
* vCard array element schema.
|
|
25
|
+
* vCard format: ["property", {}, "type", value]
|
|
26
|
+
*/
|
|
27
|
+
const VCardPropertySchema = zod_1.z.tuple([
|
|
28
|
+
zod_1.z.string(), // property name (e.g., "fn")
|
|
29
|
+
zod_1.z.record(zod_1.z.unknown()), // parameters (usually empty {})
|
|
30
|
+
zod_1.z.string(), // type (e.g., "text")
|
|
31
|
+
zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]), // value
|
|
32
|
+
]).or(zod_1.z.array(zod_1.z.unknown())); // Allow flexible arrays for compatibility
|
|
33
|
+
/**
|
|
34
|
+
* Entity schema (registrar, registrant, etc.)
|
|
35
|
+
*/
|
|
36
|
+
const RdapEntitySchema = zod_1.z.object({
|
|
37
|
+
roles: zod_1.z.array(zod_1.z.string()).optional(),
|
|
38
|
+
vcardArray: zod_1.z.tuple([
|
|
39
|
+
zod_1.z.literal('vcard'),
|
|
40
|
+
zod_1.z.array(VCardPropertySchema),
|
|
41
|
+
]).optional(),
|
|
42
|
+
}).passthrough(); // Allow additional RDAP fields
|
|
43
|
+
/**
|
|
44
|
+
* RDAP event schema (registration, expiration, etc.)
|
|
45
|
+
*/
|
|
46
|
+
const RdapEventSchema = zod_1.z.object({
|
|
47
|
+
eventAction: zod_1.z.string(),
|
|
48
|
+
eventDate: zod_1.z.string(),
|
|
49
|
+
}).passthrough();
|
|
50
|
+
/**
|
|
51
|
+
* Main RDAP domain response schema.
|
|
52
|
+
*/
|
|
53
|
+
const RdapDomainResponseSchema = zod_1.z.object({
|
|
54
|
+
objectClassName: zod_1.z.string(),
|
|
55
|
+
ldhName: zod_1.z.string().optional(),
|
|
56
|
+
entities: zod_1.z.array(RdapEntitySchema).optional(),
|
|
57
|
+
events: zod_1.z.array(RdapEventSchema).optional(),
|
|
58
|
+
}).passthrough(); // Allow additional RDAP fields
|
|
59
|
+
/**
|
|
60
|
+
* RDAP bootstrap URLs for different TLDs.
|
|
61
|
+
*/
|
|
62
|
+
const RDAP_BOOTSTRAP = 'https://data.iana.org/rdap/dns.json';
|
|
63
|
+
/**
|
|
64
|
+
* Fallback RDAP servers for common TLDs.
|
|
65
|
+
* Expanded to include popular gTLDs and ccTLDs.
|
|
66
|
+
*/
|
|
67
|
+
const RDAP_SERVERS = {
|
|
68
|
+
// Generic TLDs (Verisign)
|
|
69
|
+
com: 'https://rdap.verisign.com/com/v1',
|
|
70
|
+
net: 'https://rdap.verisign.com/net/v1',
|
|
71
|
+
cc: 'https://rdap.verisign.com/cc/v1',
|
|
72
|
+
tv: 'https://rdap.verisign.com/tv/v1',
|
|
73
|
+
name: 'https://rdap.verisign.com/name/v1',
|
|
74
|
+
// Generic TLDs (Other registries)
|
|
75
|
+
org: 'https://rdap.publicinterestregistry.org/rdap/org',
|
|
76
|
+
info: 'https://rdap.afilias.net/rdap/info',
|
|
77
|
+
biz: 'https://rdap.nic.biz',
|
|
78
|
+
xyz: 'https://rdap.nic.xyz',
|
|
79
|
+
club: 'https://rdap.nic.club',
|
|
80
|
+
online: 'https://rdap.nic.online',
|
|
81
|
+
site: 'https://rdap.nic.site',
|
|
82
|
+
tech: 'https://rdap.nic.tech',
|
|
83
|
+
store: 'https://rdap.nic.store',
|
|
84
|
+
// Google TLDs
|
|
85
|
+
dev: 'https://rdap.nic.google/domain',
|
|
86
|
+
app: 'https://rdap.nic.google/domain',
|
|
87
|
+
page: 'https://rdap.nic.google/domain',
|
|
88
|
+
how: 'https://rdap.nic.google/domain',
|
|
89
|
+
new: 'https://rdap.nic.google/domain',
|
|
90
|
+
// Country-code TLDs (ccTLDs)
|
|
91
|
+
io: 'https://rdap.nic.io/domain',
|
|
92
|
+
co: 'https://rdap.nic.co/domain',
|
|
93
|
+
ai: 'https://rdap.nic.ai/domain',
|
|
94
|
+
me: 'https://rdap.nic.me/domain',
|
|
95
|
+
sh: 'https://rdap.nic.sh/domain',
|
|
96
|
+
ac: 'https://rdap.nic.ac/domain',
|
|
97
|
+
gg: 'https://rdap.nic.gg/domain',
|
|
98
|
+
im: 'https://rdap.nic.im/domain',
|
|
99
|
+
// European ccTLDs
|
|
100
|
+
eu: 'https://rdap.eurid.eu/domain',
|
|
101
|
+
de: 'https://rdap.denic.de/domain',
|
|
102
|
+
nl: 'https://rdap.sidn.nl',
|
|
103
|
+
uk: 'https://rdap.nominet.uk/uk',
|
|
104
|
+
ch: 'https://rdap.nic.ch',
|
|
105
|
+
se: 'https://rdap.iis.se/domain',
|
|
106
|
+
fi: 'https://rdap.traficom.fi/domain',
|
|
107
|
+
cz: 'https://rdap.nic.cz',
|
|
108
|
+
pl: 'https://rdap.dns.pl',
|
|
109
|
+
// Other popular ccTLDs
|
|
110
|
+
ca: 'https://rdap.ca.fury.ca/rdap',
|
|
111
|
+
au: 'https://rdap.auda.org.au',
|
|
112
|
+
nz: 'https://rdap.dnc.org.nz',
|
|
113
|
+
jp: 'https://rdap.jprs.jp/rdap',
|
|
114
|
+
kr: 'https://rdap.kisa.or.kr',
|
|
115
|
+
in: 'https://rdap.registry.in',
|
|
116
|
+
br: 'https://rdap.registro.br',
|
|
117
|
+
// Specialty TLDs
|
|
118
|
+
crypto: 'https://rdap.nic.crypto',
|
|
119
|
+
cloud: 'https://rdap.nic.cloud',
|
|
120
|
+
design: 'https://rdap.nic.design',
|
|
121
|
+
agency: 'https://rdap.nic.agency',
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Cache for RDAP server lookups.
|
|
125
|
+
*/
|
|
126
|
+
let rdapServerCache = null;
|
|
127
|
+
/**
|
|
128
|
+
* Get the RDAP server URL for a TLD.
|
|
129
|
+
*/
|
|
130
|
+
async function getRdapServer(tld) {
|
|
131
|
+
// Check hardcoded servers first
|
|
132
|
+
if (RDAP_SERVERS[tld]) {
|
|
133
|
+
return RDAP_SERVERS[tld];
|
|
134
|
+
}
|
|
135
|
+
// Try to fetch from IANA bootstrap
|
|
136
|
+
try {
|
|
137
|
+
if (!rdapServerCache) {
|
|
138
|
+
const response = await axios_1.default.get(RDAP_BOOTSTRAP, { timeout: 5000 });
|
|
139
|
+
rdapServerCache = {};
|
|
140
|
+
for (const [tlds, servers] of response.data.services) {
|
|
141
|
+
for (const t of tlds) {
|
|
142
|
+
rdapServerCache[t] = servers[0] || '';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return rdapServerCache[tld] || null;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
logger_js_1.logger.debug('Failed to fetch RDAP bootstrap', { tld });
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Safely extract registrar name from vCard array.
|
|
155
|
+
* SECURITY: Validates array bounds and types before access.
|
|
156
|
+
*/
|
|
157
|
+
function extractRegistrarFromVCard(vcardArray) {
|
|
158
|
+
try {
|
|
159
|
+
// vcardArray should be ["vcard", [...properties]]
|
|
160
|
+
if (!Array.isArray(vcardArray) || vcardArray.length < 2) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
const properties = vcardArray[1];
|
|
164
|
+
if (!Array.isArray(properties)) {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
// Find the "fn" (formatted name) property
|
|
168
|
+
for (const prop of properties) {
|
|
169
|
+
if (!Array.isArray(prop) || prop.length < 4) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const [propName, , , propValue] = prop;
|
|
173
|
+
if (propName === 'fn' && typeof propValue === 'string') {
|
|
174
|
+
return propValue;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
logger_js_1.logger.debug('Failed to extract registrar from vCard', {
|
|
181
|
+
error: error instanceof Error ? error.message : String(error),
|
|
182
|
+
});
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Parse RDAP response to determine availability and extract dates.
|
|
188
|
+
* SECURITY: Validates response with Zod schema before processing.
|
|
189
|
+
*/
|
|
190
|
+
function parseRdapResponse(data) {
|
|
191
|
+
if (!data || typeof data !== 'object') {
|
|
192
|
+
return { available: false };
|
|
193
|
+
}
|
|
194
|
+
// Validate with Zod schema
|
|
195
|
+
const parseResult = RdapDomainResponseSchema.safeParse(data);
|
|
196
|
+
if (!parseResult.success) {
|
|
197
|
+
logger_js_1.logger.debug('RDAP response validation failed', {
|
|
198
|
+
errors: parseResult.error.errors.slice(0, 3), // Limit logged errors
|
|
199
|
+
});
|
|
200
|
+
// Still try to extract basic info even if validation fails
|
|
201
|
+
const record = data;
|
|
202
|
+
if (record.objectClassName === 'domain') {
|
|
203
|
+
return { available: false };
|
|
204
|
+
}
|
|
205
|
+
return { available: false };
|
|
206
|
+
}
|
|
207
|
+
const validated = parseResult.data;
|
|
208
|
+
// If we got a domain record, it's registered (not available)
|
|
209
|
+
if (validated.objectClassName === 'domain') {
|
|
210
|
+
let registrar;
|
|
211
|
+
let registeredAt;
|
|
212
|
+
let expiresAt;
|
|
213
|
+
// Safely extract registrar info
|
|
214
|
+
if (validated.entities) {
|
|
215
|
+
for (const entity of validated.entities) {
|
|
216
|
+
if (entity.roles?.includes('registrar') && entity.vcardArray) {
|
|
217
|
+
registrar = extractRegistrarFromVCard(entity.vcardArray);
|
|
218
|
+
if (registrar)
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Extract event dates (registration, expiration, last changed)
|
|
224
|
+
if (validated.events) {
|
|
225
|
+
for (const event of validated.events) {
|
|
226
|
+
const action = event.eventAction.toLowerCase();
|
|
227
|
+
if (action === 'registration' || action === 'created') {
|
|
228
|
+
registeredAt = event.eventDate;
|
|
229
|
+
}
|
|
230
|
+
else if (action === 'expiration') {
|
|
231
|
+
expiresAt = event.eventDate;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { available: false, registrar, registeredAt, expiresAt };
|
|
236
|
+
}
|
|
237
|
+
return { available: false };
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Check domain availability using RDAP.
|
|
241
|
+
*/
|
|
242
|
+
async function checkRdap(domain, tld) {
|
|
243
|
+
const fullDomain = `${domain}.${tld}`;
|
|
244
|
+
logger_js_1.logger.debug('RDAP check', { domain: fullDomain });
|
|
245
|
+
const server = await getRdapServer(tld);
|
|
246
|
+
if (!server) {
|
|
247
|
+
throw new errors_js_1.RegistrarApiError('rdap', `No RDAP server found for .${tld}`);
|
|
248
|
+
}
|
|
249
|
+
const url = `${server}/domain/${fullDomain}`;
|
|
250
|
+
try {
|
|
251
|
+
const response = await axios_1.default.get(url, {
|
|
252
|
+
timeout: 10000,
|
|
253
|
+
headers: {
|
|
254
|
+
Accept: 'application/rdap+json',
|
|
255
|
+
},
|
|
256
|
+
// Don't throw on 404 - that means available
|
|
257
|
+
validateStatus: (status) => status < 500,
|
|
258
|
+
});
|
|
259
|
+
// 404 = domain not found = available
|
|
260
|
+
if (response.status === 404) {
|
|
261
|
+
return createRdapResult(domain, tld, true);
|
|
262
|
+
}
|
|
263
|
+
// 200 = domain found = not available
|
|
264
|
+
if (response.status === 200) {
|
|
265
|
+
const parsed = parseRdapResponse(response.data);
|
|
266
|
+
return createRdapResult(domain, tld, parsed.available, {
|
|
267
|
+
registeredAt: parsed.registeredAt,
|
|
268
|
+
expiresAt: parsed.expiresAt,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
throw new errors_js_1.RegistrarApiError('rdap', `Unexpected response: HTTP ${response.status}`);
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
275
|
+
const axiosError = error;
|
|
276
|
+
if (axiosError.code === 'ECONNABORTED') {
|
|
277
|
+
throw new errors_js_1.TimeoutError('RDAP lookup', 10000);
|
|
278
|
+
}
|
|
279
|
+
// 404 = available
|
|
280
|
+
if (axiosError.response?.status === 404) {
|
|
281
|
+
return createRdapResult(domain, tld, true);
|
|
282
|
+
}
|
|
283
|
+
throw new errors_js_1.RegistrarApiError('rdap', axiosError.message, axiosError.response?.status, error);
|
|
284
|
+
}
|
|
285
|
+
throw new errors_js_1.RegistrarApiError('rdap', error instanceof Error ? error.message : 'Unknown error');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Calculate days until expiration from an ISO date string.
|
|
290
|
+
*/
|
|
291
|
+
function calculateDaysUntilExpiration(expiresAt) {
|
|
292
|
+
try {
|
|
293
|
+
const expirationDate = new Date(expiresAt);
|
|
294
|
+
const now = new Date();
|
|
295
|
+
const diffMs = expirationDate.getTime() - now.getTime();
|
|
296
|
+
const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24));
|
|
297
|
+
return diffDays;
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Create a standardized result from RDAP.
|
|
305
|
+
*/
|
|
306
|
+
function createRdapResult(domain, tld, available, dates) {
|
|
307
|
+
const result = {
|
|
308
|
+
domain: `${domain}.${tld}`,
|
|
309
|
+
available,
|
|
310
|
+
premium: false, // RDAP doesn't tell us about premium status
|
|
311
|
+
price_first_year: null, // RDAP doesn't provide pricing
|
|
312
|
+
price_renewal: null,
|
|
313
|
+
currency: 'USD',
|
|
314
|
+
privacy_included: false,
|
|
315
|
+
transfer_price: null,
|
|
316
|
+
registrar: 'unknown',
|
|
317
|
+
source: 'rdap',
|
|
318
|
+
checked_at: new Date().toISOString(),
|
|
319
|
+
};
|
|
320
|
+
// Add registration and expiration dates if available
|
|
321
|
+
if (dates?.registeredAt) {
|
|
322
|
+
result.registered_at = dates.registeredAt;
|
|
323
|
+
}
|
|
324
|
+
if (dates?.expiresAt) {
|
|
325
|
+
result.expires_at = dates.expiresAt;
|
|
326
|
+
result.days_until_expiration = calculateDaysUntilExpiration(dates.expiresAt);
|
|
327
|
+
}
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Check if RDAP is available for a TLD (synchronous check).
|
|
332
|
+
* Uses hardcoded servers only for quick check.
|
|
333
|
+
*/
|
|
334
|
+
function isRdapAvailable(tld) {
|
|
335
|
+
// Use hardcoded servers for sync check
|
|
336
|
+
// The async bootstrap will be tried during actual lookup
|
|
337
|
+
return RDAP_SERVERS[tld] !== undefined;
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=rdap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rdap.js","sourceRoot":"","sources":["../../src/fallbacks/rdap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHOIS Fallback (RFC 3912).
|
|
3
|
+
*
|
|
4
|
+
* Legacy protocol for domain lookup.
|
|
5
|
+
* Public, no authentication required.
|
|
6
|
+
* Slower than RDAP - use as last resort.
|
|
7
|
+
*
|
|
8
|
+
* Note: We use a public WHOIS API to avoid raw TCP connections
|
|
9
|
+
* which aren't well-supported in all Node.js environments.
|
|
10
|
+
*/
|
|
11
|
+
import type { DomainResult } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Check domain availability using a public WHOIS API.
|
|
14
|
+
*
|
|
15
|
+
* We use a web-based WHOIS lookup to avoid TCP connection issues.
|
|
16
|
+
* This is more reliable across different environments.
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkWhois(domain: string, tld: string): Promise<DomainResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Get WHOIS server for a TLD.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getWhoisServer(tld: string): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Check if WHOIS is available for a TLD.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isWhoisAvailable(tld: string): boolean;
|
|
27
|
+
//# sourceMappingURL=whois.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whois.d.ts","sourceRoot":"","sources":["../../src/fallbacks/whois.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAyEhD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,CAAC,CAmEvB;AA4ED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WHOIS Fallback (RFC 3912).
|
|
4
|
+
*
|
|
5
|
+
* Legacy protocol for domain lookup.
|
|
6
|
+
* Public, no authentication required.
|
|
7
|
+
* Slower than RDAP - use as last resort.
|
|
8
|
+
*
|
|
9
|
+
* Note: We use a public WHOIS API to avoid raw TCP connections
|
|
10
|
+
* which aren't well-supported in all Node.js environments.
|
|
11
|
+
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.checkWhois = checkWhois;
|
|
17
|
+
exports.getWhoisServer = getWhoisServer;
|
|
18
|
+
exports.isWhoisAvailable = isWhoisAvailable;
|
|
19
|
+
const axios_1 = __importDefault(require("axios"));
|
|
20
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
21
|
+
const errors_js_1 = require("../utils/errors.js");
|
|
22
|
+
/**
|
|
23
|
+
* WHOIS server mappings for common TLDs.
|
|
24
|
+
*/
|
|
25
|
+
const WHOIS_SERVERS = {
|
|
26
|
+
com: 'whois.verisign-grs.com',
|
|
27
|
+
net: 'whois.verisign-grs.com',
|
|
28
|
+
org: 'whois.pir.org',
|
|
29
|
+
io: 'whois.nic.io',
|
|
30
|
+
dev: 'whois.nic.google',
|
|
31
|
+
app: 'whois.nic.google',
|
|
32
|
+
co: 'whois.nic.co',
|
|
33
|
+
ai: 'whois.nic.ai',
|
|
34
|
+
me: 'whois.nic.me',
|
|
35
|
+
cc: 'ccwhois.verisign-grs.com',
|
|
36
|
+
xyz: 'whois.nic.xyz',
|
|
37
|
+
sh: 'whois.nic.sh',
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Patterns that indicate a domain is NOT available.
|
|
41
|
+
*/
|
|
42
|
+
const REGISTERED_PATTERNS = [
|
|
43
|
+
/domain name:/i,
|
|
44
|
+
/registrant:/i,
|
|
45
|
+
/creation date:/i,
|
|
46
|
+
/name server:/i,
|
|
47
|
+
/status:\s*(?:active|ok|registered)/i,
|
|
48
|
+
];
|
|
49
|
+
/**
|
|
50
|
+
* Patterns that indicate a domain IS available.
|
|
51
|
+
*/
|
|
52
|
+
const AVAILABLE_PATTERNS = [
|
|
53
|
+
/no match/i,
|
|
54
|
+
/not found/i,
|
|
55
|
+
/no data found/i,
|
|
56
|
+
/no entries found/i,
|
|
57
|
+
/no object found/i,
|
|
58
|
+
/domain not found/i,
|
|
59
|
+
/no whois server/i,
|
|
60
|
+
/available for registration/i,
|
|
61
|
+
/is free/i,
|
|
62
|
+
/status:\s*free/i,
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Parse WHOIS response to determine availability.
|
|
66
|
+
*/
|
|
67
|
+
function parseWhoisResponse(response) {
|
|
68
|
+
const text = response.toLowerCase();
|
|
69
|
+
// Check for "available" patterns first
|
|
70
|
+
for (const pattern of AVAILABLE_PATTERNS) {
|
|
71
|
+
if (pattern.test(text)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Check for "registered" patterns
|
|
76
|
+
for (const pattern of REGISTERED_PATTERNS) {
|
|
77
|
+
if (pattern.test(text)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// If no clear indication, assume not available (safer)
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check domain availability using a public WHOIS API.
|
|
86
|
+
*
|
|
87
|
+
* We use a web-based WHOIS lookup to avoid TCP connection issues.
|
|
88
|
+
* This is more reliable across different environments.
|
|
89
|
+
*/
|
|
90
|
+
async function checkWhois(domain, tld) {
|
|
91
|
+
const fullDomain = `${domain}.${tld}`;
|
|
92
|
+
logger_js_1.logger.debug('WHOIS check', { domain: fullDomain });
|
|
93
|
+
// Use a public WHOIS API service
|
|
94
|
+
// There are several options; we'll try a few
|
|
95
|
+
const apis = [
|
|
96
|
+
{
|
|
97
|
+
url: `https://whoisjson.com/api/v1/whois`,
|
|
98
|
+
params: { domain: fullDomain },
|
|
99
|
+
parser: (data) => {
|
|
100
|
+
// If we get a result, domain is registered
|
|
101
|
+
if (data.domain_name || data.registrar) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
// If error or no data, domain might be available
|
|
105
|
+
return true;
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
// Try each API in order
|
|
110
|
+
for (const api of apis) {
|
|
111
|
+
try {
|
|
112
|
+
const response = await axios_1.default.get(api.url, {
|
|
113
|
+
params: api.params,
|
|
114
|
+
timeout: 15000,
|
|
115
|
+
headers: {
|
|
116
|
+
Accept: 'application/json',
|
|
117
|
+
},
|
|
118
|
+
validateStatus: () => true, // Don't throw on any status
|
|
119
|
+
});
|
|
120
|
+
if (response.status === 200 && response.data) {
|
|
121
|
+
// Try to parse the response
|
|
122
|
+
let available;
|
|
123
|
+
if (typeof response.data === 'string') {
|
|
124
|
+
available = parseWhoisResponse(response.data);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
available = api.parser(response.data);
|
|
128
|
+
}
|
|
129
|
+
return createWhoisResult(domain, tld, available);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger_js_1.logger.debug('WHOIS API failed, trying next', {
|
|
134
|
+
api: api.url,
|
|
135
|
+
error: error instanceof Error ? error.message : String(error),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// If all APIs fail, try a simple text-based WHOIS lookup
|
|
140
|
+
try {
|
|
141
|
+
const available = await textBasedWhoisCheck(fullDomain, tld);
|
|
142
|
+
return createWhoisResult(domain, tld, available);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (error instanceof Error && error.message.includes('timeout')) {
|
|
146
|
+
throw new errors_js_1.TimeoutError('WHOIS lookup', 15000);
|
|
147
|
+
}
|
|
148
|
+
throw new errors_js_1.RegistrarApiError('whois', error instanceof Error ? error.message : 'All WHOIS lookups failed');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Simple text-based WHOIS check using a web proxy.
|
|
153
|
+
*/
|
|
154
|
+
async function textBasedWhoisCheck(fullDomain, tld) {
|
|
155
|
+
// Try who.is web service
|
|
156
|
+
try {
|
|
157
|
+
const response = await axios_1.default.get(`https://who.is/whois/${fullDomain}`, {
|
|
158
|
+
timeout: 15000,
|
|
159
|
+
headers: {
|
|
160
|
+
'User-Agent': 'Domain-Search-MCP/1.0',
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
const html = response.data;
|
|
164
|
+
// Check for "not registered" indicators in the page
|
|
165
|
+
if (html.includes('is available for registration') ||
|
|
166
|
+
html.includes('No match for') ||
|
|
167
|
+
html.includes('not found')) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
// Check for registered indicators
|
|
171
|
+
if (html.includes('Registrar:') ||
|
|
172
|
+
html.includes('Creation Date:') ||
|
|
173
|
+
html.includes('Name Server:')) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
// Default to not available
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
181
|
+
const axiosError = error;
|
|
182
|
+
if (axiosError.code === 'ECONNABORTED') {
|
|
183
|
+
throw new Error('timeout');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Create a standardized result from WHOIS.
|
|
191
|
+
*/
|
|
192
|
+
function createWhoisResult(domain, tld, available) {
|
|
193
|
+
return {
|
|
194
|
+
domain: `${domain}.${tld}`,
|
|
195
|
+
available,
|
|
196
|
+
premium: false, // WHOIS doesn't tell us about premium status
|
|
197
|
+
price_first_year: null, // WHOIS doesn't provide pricing
|
|
198
|
+
price_renewal: null,
|
|
199
|
+
currency: 'USD',
|
|
200
|
+
privacy_included: false,
|
|
201
|
+
transfer_price: null,
|
|
202
|
+
registrar: 'unknown',
|
|
203
|
+
source: 'whois',
|
|
204
|
+
checked_at: new Date().toISOString(),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get WHOIS server for a TLD.
|
|
209
|
+
*/
|
|
210
|
+
function getWhoisServer(tld) {
|
|
211
|
+
return WHOIS_SERVERS[tld] || null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Check if WHOIS is available for a TLD.
|
|
215
|
+
*/
|
|
216
|
+
function isWhoisAvailable(tld) {
|
|
217
|
+
return WHOIS_SERVERS[tld] !== undefined;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=whois.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whois.js","sourceRoot":"","sources":["../../src/fallbacks/whois.ts"],"names":[],"mappings":"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"}
|