domain-alive 0.1.5 → 0.1.6
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/dist/index.js +22 -17
- package/dist/index.mjs +22 -17
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -26,20 +26,16 @@ function getDnsClients(servers) {
|
|
|
26
26
|
return servers.map((dns)=>{
|
|
27
27
|
const protocolIndex = dns.indexOf('://');
|
|
28
28
|
const protocol = protocolIndex === -1 ? '' : dns.slice(0, protocolIndex);
|
|
29
|
-
const
|
|
30
|
-
const [server, _port] = rest.split(':', 2);
|
|
29
|
+
const [server, _port] = dns.slice(protocolIndex + 3).split(':', 2);
|
|
31
30
|
const port = _port ? Number.parseInt(_port, 10) : 0;
|
|
32
31
|
let client;
|
|
33
32
|
switch(protocol){
|
|
34
33
|
case 'https':
|
|
35
34
|
{
|
|
36
|
-
// TODO: fuck dns2 incorrect DOHClient server parse impl
|
|
37
35
|
const u = new URL(dns);
|
|
38
|
-
if (
|
|
36
|
+
if (!server.includes('/')) {
|
|
39
37
|
u.pathname = '/dns-query';
|
|
40
38
|
}
|
|
41
|
-
// u.searchParams.set('dns', '{query}');
|
|
42
|
-
u.search = '?dns={query}';
|
|
43
39
|
client = dns2.DOHClient({
|
|
44
40
|
dns: u.href
|
|
45
41
|
});
|
|
@@ -1188,7 +1184,7 @@ const whoiserNoWhoisSymbol = Symbol('"whoiser" library returns "No WHOIS data fo
|
|
|
1188
1184
|
return whoisErrorCountAsAlive;
|
|
1189
1185
|
}
|
|
1190
1186
|
if (whois === whoiserTLDNotSupportedSymbol) {
|
|
1191
|
-
// If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's
|
|
1187
|
+
// If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's registered
|
|
1192
1188
|
return true;
|
|
1193
1189
|
}
|
|
1194
1190
|
if (whois === whoiserNoWhoisSymbol) {
|
|
@@ -1225,12 +1221,12 @@ const whoisNotFoundKeywordTest = retrie.createRetrieKeywordFilter([
|
|
|
1225
1221
|
// some servers (like TLD whois servers) might have cached/outdated results
|
|
1226
1222
|
// we can only make sure a domain is alive once all response from all whois servers demonstrate so
|
|
1227
1223
|
function walkWhois(whois) {
|
|
1228
|
-
// eslint-disable-next-line sukka/no-single-return -- mutable
|
|
1229
1224
|
let whoisIsEmpty = true;
|
|
1230
1225
|
if ('__raw' in whois && typeof whois.__raw === 'string') {
|
|
1231
1226
|
const lines = whois.__raw.trim().toLowerCase().replaceAll(/[\t ]+/g, ' ').split(/\r?\n/);
|
|
1232
1227
|
for (const line of lines){
|
|
1233
1228
|
if (whoisNotFoundKeywordTest(line)) {
|
|
1229
|
+
log$2('[whois] line %s, %O', line, whois);
|
|
1234
1230
|
return false;
|
|
1235
1231
|
}
|
|
1236
1232
|
}
|
|
@@ -1238,7 +1234,6 @@ function walkWhois(whois) {
|
|
|
1238
1234
|
// so we can't determine if the domain has been registered or not, that's OK, we can check the referrer/follow/redirected whois output.
|
|
1239
1235
|
for(const key in whois){
|
|
1240
1236
|
if (Object.hasOwn(whois, key)) {
|
|
1241
|
-
// eslint-disable-next-line sukka/no-single-return -- mutable
|
|
1242
1237
|
whoisIsEmpty = false;
|
|
1243
1238
|
if (key === '__raw') {
|
|
1244
1239
|
continue;
|
|
@@ -1253,8 +1248,8 @@ function walkWhois(whois) {
|
|
|
1253
1248
|
}
|
|
1254
1249
|
}
|
|
1255
1250
|
}
|
|
1256
|
-
|
|
1257
|
-
return whoisIsEmpty;
|
|
1251
|
+
log$2('[whois] %O', whois);
|
|
1252
|
+
return !whoisIsEmpty;
|
|
1258
1253
|
}
|
|
1259
1254
|
|
|
1260
1255
|
async function cacheApply(cache, key, fn) {
|
|
@@ -1284,6 +1279,7 @@ async function cacheApply(cache, key, fn) {
|
|
|
1284
1279
|
}
|
|
1285
1280
|
|
|
1286
1281
|
const log$1 = debug__default.default('domain-alive:is-registerable-domain-alive');
|
|
1282
|
+
const deadLog$1 = debug__default.default('domain-alive:dead-domain');
|
|
1287
1283
|
const getRegisterableDomainTldtsOption = {
|
|
1288
1284
|
allowIcannDomains: true,
|
|
1289
1285
|
// we want to extract "github.io" out of "sukkaw.github.io" even though github.io is in the
|
|
@@ -1358,7 +1354,6 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
|
|
|
1358
1354
|
let confirmations = 0;
|
|
1359
1355
|
while(attempts < maxAttempts){
|
|
1360
1356
|
if (confirmations >= maxConfirmations) {
|
|
1361
|
-
log$1('[status] %s %s', registerableDomain, true);
|
|
1362
1357
|
return {
|
|
1363
1358
|
registerableDomain,
|
|
1364
1359
|
alive: true
|
|
@@ -1387,13 +1382,14 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
|
|
|
1387
1382
|
try {
|
|
1388
1383
|
const registered = await domainHasBeenRegistered(registerableDomain, whoisOptions);
|
|
1389
1384
|
log$1('[whois] %s %s', registerableDomain, registered);
|
|
1390
|
-
|
|
1385
|
+
if (!registered) {
|
|
1386
|
+
deadLog$1('[dead] %s %s', '(apex)', registerableDomain);
|
|
1387
|
+
}
|
|
1391
1388
|
return {
|
|
1392
1389
|
registerableDomain,
|
|
1393
1390
|
alive: registered
|
|
1394
1391
|
};
|
|
1395
1392
|
} catch {
|
|
1396
|
-
log$1('[status] %s %s', registerableDomain, whoisOptions.whoisErrorCountAsAlive ?? true);
|
|
1397
1393
|
return {
|
|
1398
1394
|
registerableDomain,
|
|
1399
1395
|
alive: whoisOptions.whoisErrorCountAsAlive ?? true
|
|
@@ -1404,6 +1400,7 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
|
|
|
1404
1400
|
}
|
|
1405
1401
|
|
|
1406
1402
|
const log = debug__default.default('domain-alive:is-domain-alive');
|
|
1403
|
+
const deadLog = debug__default.default('domain-alive:dead-domain');
|
|
1407
1404
|
const sharedNullishResult = Object.freeze({
|
|
1408
1405
|
registerableDomain: null,
|
|
1409
1406
|
registerableDomainAlive: false,
|
|
@@ -1455,7 +1452,6 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1455
1452
|
let confirmations = 0;
|
|
1456
1453
|
while(attempts < maxAttempts){
|
|
1457
1454
|
if (confirmations >= maxConfirmations) {
|
|
1458
|
-
log('[status] %s %s', domain, true);
|
|
1459
1455
|
return {
|
|
1460
1456
|
registerableDomain: registerableDomainAliveResult.registerableDomain,
|
|
1461
1457
|
registerableDomainAlive: registerableDomainAliveResult.alive,
|
|
@@ -1471,6 +1467,11 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1471
1467
|
confirmations++;
|
|
1472
1468
|
}
|
|
1473
1469
|
} catch (e) {
|
|
1470
|
+
if (typeof e === 'object' && e !== null) {
|
|
1471
|
+
Object.assign(e, {
|
|
1472
|
+
dns: resolve.server
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1474
1475
|
log('[A] %s error %O', domain, e);
|
|
1475
1476
|
} finally{
|
|
1476
1477
|
attempts++;
|
|
@@ -1484,7 +1485,6 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1484
1485
|
let confirmations = 0;
|
|
1485
1486
|
while(attempts < maxAttempts){
|
|
1486
1487
|
if (confirmations >= maxConfirmations) {
|
|
1487
|
-
log('[status] %s %s', domain, true);
|
|
1488
1488
|
return {
|
|
1489
1489
|
registerableDomain: registerableDomainAliveResult.registerableDomain,
|
|
1490
1490
|
registerableDomainAlive: registerableDomainAliveResult.alive,
|
|
@@ -1500,6 +1500,11 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1500
1500
|
confirmations++;
|
|
1501
1501
|
}
|
|
1502
1502
|
} catch (e) {
|
|
1503
|
+
if (typeof e === 'object' && e !== null) {
|
|
1504
|
+
Object.assign(e, {
|
|
1505
|
+
dns: resolve.server
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1503
1508
|
log('[AAAA] %s error %O', domain, e);
|
|
1504
1509
|
} finally{
|
|
1505
1510
|
attempts++;
|
|
@@ -1508,7 +1513,7 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1508
1513
|
}
|
|
1509
1514
|
}
|
|
1510
1515
|
// neither A nor AAAA records found
|
|
1511
|
-
|
|
1516
|
+
deadLog('[dead] %s %s', '(A/AAAA)', domain);
|
|
1512
1517
|
return {
|
|
1513
1518
|
registerableDomain: registerableDomainAliveResult.registerableDomain,
|
|
1514
1519
|
registerableDomainAlive: registerableDomainAliveResult.alive,
|
package/dist/index.mjs
CHANGED
|
@@ -18,20 +18,16 @@ function getDnsClients(servers) {
|
|
|
18
18
|
return servers.map((dns)=>{
|
|
19
19
|
const protocolIndex = dns.indexOf('://');
|
|
20
20
|
const protocol = protocolIndex === -1 ? '' : dns.slice(0, protocolIndex);
|
|
21
|
-
const
|
|
22
|
-
const [server, _port] = rest.split(':', 2);
|
|
21
|
+
const [server, _port] = dns.slice(protocolIndex + 3).split(':', 2);
|
|
23
22
|
const port = _port ? Number.parseInt(_port, 10) : 0;
|
|
24
23
|
let client;
|
|
25
24
|
switch(protocol){
|
|
26
25
|
case 'https':
|
|
27
26
|
{
|
|
28
|
-
// TODO: fuck dns2 incorrect DOHClient server parse impl
|
|
29
27
|
const u = new URL(dns);
|
|
30
|
-
if (
|
|
28
|
+
if (!server.includes('/')) {
|
|
31
29
|
u.pathname = '/dns-query';
|
|
32
30
|
}
|
|
33
|
-
// u.searchParams.set('dns', '{query}');
|
|
34
|
-
u.search = '?dns={query}';
|
|
35
31
|
client = DOHClient({
|
|
36
32
|
dns: u.href
|
|
37
33
|
});
|
|
@@ -1180,7 +1176,7 @@ const whoiserNoWhoisSymbol = Symbol('"whoiser" library returns "No WHOIS data fo
|
|
|
1180
1176
|
return whoisErrorCountAsAlive;
|
|
1181
1177
|
}
|
|
1182
1178
|
if (whois === whoiserTLDNotSupportedSymbol) {
|
|
1183
|
-
// If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's
|
|
1179
|
+
// If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's registered
|
|
1184
1180
|
return true;
|
|
1185
1181
|
}
|
|
1186
1182
|
if (whois === whoiserNoWhoisSymbol) {
|
|
@@ -1217,12 +1213,12 @@ const whoisNotFoundKeywordTest = createRetrieKeywordFilter([
|
|
|
1217
1213
|
// some servers (like TLD whois servers) might have cached/outdated results
|
|
1218
1214
|
// we can only make sure a domain is alive once all response from all whois servers demonstrate so
|
|
1219
1215
|
function walkWhois(whois) {
|
|
1220
|
-
// eslint-disable-next-line sukka/no-single-return -- mutable
|
|
1221
1216
|
let whoisIsEmpty = true;
|
|
1222
1217
|
if ('__raw' in whois && typeof whois.__raw === 'string') {
|
|
1223
1218
|
const lines = whois.__raw.trim().toLowerCase().replaceAll(/[\t ]+/g, ' ').split(/\r?\n/);
|
|
1224
1219
|
for (const line of lines){
|
|
1225
1220
|
if (whoisNotFoundKeywordTest(line)) {
|
|
1221
|
+
log$2('[whois] line %s, %O', line, whois);
|
|
1226
1222
|
return false;
|
|
1227
1223
|
}
|
|
1228
1224
|
}
|
|
@@ -1230,7 +1226,6 @@ function walkWhois(whois) {
|
|
|
1230
1226
|
// so we can't determine if the domain has been registered or not, that's OK, we can check the referrer/follow/redirected whois output.
|
|
1231
1227
|
for(const key in whois){
|
|
1232
1228
|
if (Object.hasOwn(whois, key)) {
|
|
1233
|
-
// eslint-disable-next-line sukka/no-single-return -- mutable
|
|
1234
1229
|
whoisIsEmpty = false;
|
|
1235
1230
|
if (key === '__raw') {
|
|
1236
1231
|
continue;
|
|
@@ -1245,8 +1240,8 @@ function walkWhois(whois) {
|
|
|
1245
1240
|
}
|
|
1246
1241
|
}
|
|
1247
1242
|
}
|
|
1248
|
-
|
|
1249
|
-
return whoisIsEmpty;
|
|
1243
|
+
log$2('[whois] %O', whois);
|
|
1244
|
+
return !whoisIsEmpty;
|
|
1250
1245
|
}
|
|
1251
1246
|
|
|
1252
1247
|
async function cacheApply(cache, key, fn) {
|
|
@@ -1276,6 +1271,7 @@ async function cacheApply(cache, key, fn) {
|
|
|
1276
1271
|
}
|
|
1277
1272
|
|
|
1278
1273
|
const log$1 = debug('domain-alive:is-registerable-domain-alive');
|
|
1274
|
+
const deadLog$1 = debug('domain-alive:dead-domain');
|
|
1279
1275
|
const getRegisterableDomainTldtsOption = {
|
|
1280
1276
|
allowIcannDomains: true,
|
|
1281
1277
|
// we want to extract "github.io" out of "sukkaw.github.io" even though github.io is in the
|
|
@@ -1350,7 +1346,6 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
|
|
|
1350
1346
|
let confirmations = 0;
|
|
1351
1347
|
while(attempts < maxAttempts){
|
|
1352
1348
|
if (confirmations >= maxConfirmations) {
|
|
1353
|
-
log$1('[status] %s %s', registerableDomain, true);
|
|
1354
1349
|
return {
|
|
1355
1350
|
registerableDomain,
|
|
1356
1351
|
alive: true
|
|
@@ -1379,13 +1374,14 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
|
|
|
1379
1374
|
try {
|
|
1380
1375
|
const registered = await domainHasBeenRegistered(registerableDomain, whoisOptions);
|
|
1381
1376
|
log$1('[whois] %s %s', registerableDomain, registered);
|
|
1382
|
-
|
|
1377
|
+
if (!registered) {
|
|
1378
|
+
deadLog$1('[dead] %s %s', '(apex)', registerableDomain);
|
|
1379
|
+
}
|
|
1383
1380
|
return {
|
|
1384
1381
|
registerableDomain,
|
|
1385
1382
|
alive: registered
|
|
1386
1383
|
};
|
|
1387
1384
|
} catch {
|
|
1388
|
-
log$1('[status] %s %s', registerableDomain, whoisOptions.whoisErrorCountAsAlive ?? true);
|
|
1389
1385
|
return {
|
|
1390
1386
|
registerableDomain,
|
|
1391
1387
|
alive: whoisOptions.whoisErrorCountAsAlive ?? true
|
|
@@ -1396,6 +1392,7 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
|
|
|
1396
1392
|
}
|
|
1397
1393
|
|
|
1398
1394
|
const log = debug('domain-alive:is-domain-alive');
|
|
1395
|
+
const deadLog = debug('domain-alive:dead-domain');
|
|
1399
1396
|
const sharedNullishResult = Object.freeze({
|
|
1400
1397
|
registerableDomain: null,
|
|
1401
1398
|
registerableDomainAlive: false,
|
|
@@ -1447,7 +1444,6 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1447
1444
|
let confirmations = 0;
|
|
1448
1445
|
while(attempts < maxAttempts){
|
|
1449
1446
|
if (confirmations >= maxConfirmations) {
|
|
1450
|
-
log('[status] %s %s', domain, true);
|
|
1451
1447
|
return {
|
|
1452
1448
|
registerableDomain: registerableDomainAliveResult.registerableDomain,
|
|
1453
1449
|
registerableDomainAlive: registerableDomainAliveResult.alive,
|
|
@@ -1463,6 +1459,11 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1463
1459
|
confirmations++;
|
|
1464
1460
|
}
|
|
1465
1461
|
} catch (e) {
|
|
1462
|
+
if (typeof e === 'object' && e !== null) {
|
|
1463
|
+
Object.assign(e, {
|
|
1464
|
+
dns: resolve.server
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1466
1467
|
log('[A] %s error %O', domain, e);
|
|
1467
1468
|
} finally{
|
|
1468
1469
|
attempts++;
|
|
@@ -1476,7 +1477,6 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1476
1477
|
let confirmations = 0;
|
|
1477
1478
|
while(attempts < maxAttempts){
|
|
1478
1479
|
if (confirmations >= maxConfirmations) {
|
|
1479
|
-
log('[status] %s %s', domain, true);
|
|
1480
1480
|
return {
|
|
1481
1481
|
registerableDomain: registerableDomainAliveResult.registerableDomain,
|
|
1482
1482
|
registerableDomainAlive: registerableDomainAliveResult.alive,
|
|
@@ -1492,6 +1492,11 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1492
1492
|
confirmations++;
|
|
1493
1493
|
}
|
|
1494
1494
|
} catch (e) {
|
|
1495
|
+
if (typeof e === 'object' && e !== null) {
|
|
1496
|
+
Object.assign(e, {
|
|
1497
|
+
dns: resolve.server
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1495
1500
|
log('[AAAA] %s error %O', domain, e);
|
|
1496
1501
|
} finally{
|
|
1497
1502
|
attempts++;
|
|
@@ -1500,7 +1505,7 @@ function createDomainAliveChecker(options = {}) {
|
|
|
1500
1505
|
}
|
|
1501
1506
|
}
|
|
1502
1507
|
// neither A nor AAAA records found
|
|
1503
|
-
|
|
1508
|
+
deadLog('[dead] %s %s', '(A/AAAA)', domain);
|
|
1504
1509
|
return {
|
|
1505
1510
|
registerableDomain: registerableDomainAliveResult.registerableDomain,
|
|
1506
1511
|
registerableDomainAlive: registerableDomainAliveResult.alive,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domain-alive",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A Node.js library for checking if an FQDN (Fully Qualified Domain Name) is alive or not, uses a combination techniques of `NS` records, WHOIS/RDAP lookups, `A/AAAA` records",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,13 +32,14 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"async-retry": "^1.3.3",
|
|
34
34
|
"debug": "^4.4.1",
|
|
35
|
-
"dns2": "github:lsongdev/node-dns#
|
|
35
|
+
"dns2": "github:lsongdev/node-dns#3adb7e91b3101c0e4f43ebaca3a568269ea04d11",
|
|
36
36
|
"foxts": "^3.12.0",
|
|
37
37
|
"punycode": "^2.3.1",
|
|
38
38
|
"tldts": "^7.0.12"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@eslint-sukka/node": "^6.23.1",
|
|
42
|
+
"@swc-node/register": "^1.11.1",
|
|
42
43
|
"@types/async-retry": "^1.4.9",
|
|
43
44
|
"@types/debug": "^4.1.12",
|
|
44
45
|
"@types/dns2": "^2.0.10",
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"@types/punycode": "^2.1.4",
|
|
47
48
|
"bumpp": "^10.2.3",
|
|
48
49
|
"bunchee": "^6.6.0",
|
|
49
|
-
"eslint": "^9.
|
|
50
|
+
"eslint": "^9.34.0",
|
|
50
51
|
"eslint-config-sukka": "^6.23.1",
|
|
51
52
|
"eslint-formatter-sukka": "^6.23.1",
|
|
52
53
|
"typescript": "^5.9.2",
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
"scripts": {
|
|
56
57
|
"lint": "eslint --format=sukka .",
|
|
57
58
|
"build": "bunchee --no-sourcemap",
|
|
59
|
+
"node": "node --require=@swc-node/register",
|
|
58
60
|
"prerelease": "pnpm run lint && pnpm run build",
|
|
59
61
|
"release": "bumpp -r --all --commit \"release: %s\" --tag \"%s\""
|
|
60
62
|
}
|