domain-alive 0.1.5 → 0.1.7

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.
Files changed (3) hide show
  1. package/dist/index.js +29 -21
  2. package/dist/index.mjs +29 -21
  3. package/package.json +12 -10
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 rest = dns.slice(protocolIndex + 3);
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 (u.pathname === '/') {
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
  });
@@ -1052,6 +1048,7 @@ const misspelledWhoisServer = {
1052
1048
  }
1053
1049
 
1054
1050
  const log$2 = debug__default.default('domain-alive:whois');
1051
+ const errorLog$1 = debug__default.default('domain-alive:error:whois');
1055
1052
  const getIcannTldOptions = {
1056
1053
  allowIcannDomains: true,
1057
1054
  // we want to extract "github.io" out of "sukkaw.github.io" even though github.io is in the
@@ -1184,11 +1181,11 @@ const whoiserNoWhoisSymbol = Symbol('"whoiser" library returns "No WHOIS data fo
1184
1181
  throw error;
1185
1182
  }), retryOption);
1186
1183
  } catch (e) {
1187
- log$2('[whois] %s %O', registerableDomain, e);
1184
+ errorLog$1('[whois] %s %O', registerableDomain, e);
1188
1185
  return whoisErrorCountAsAlive;
1189
1186
  }
1190
1187
  if (whois === whoiserTLDNotSupportedSymbol) {
1191
- // If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's alive
1188
+ // If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's registered
1192
1189
  return true;
1193
1190
  }
1194
1191
  if (whois === whoiserNoWhoisSymbol) {
@@ -1225,12 +1222,12 @@ const whoisNotFoundKeywordTest = retrie.createRetrieKeywordFilter([
1225
1222
  // some servers (like TLD whois servers) might have cached/outdated results
1226
1223
  // we can only make sure a domain is alive once all response from all whois servers demonstrate so
1227
1224
  function walkWhois(whois) {
1228
- // eslint-disable-next-line sukka/no-single-return -- mutable
1229
1225
  let whoisIsEmpty = true;
1230
1226
  if ('__raw' in whois && typeof whois.__raw === 'string') {
1231
1227
  const lines = whois.__raw.trim().toLowerCase().replaceAll(/[\t ]+/g, ' ').split(/\r?\n/);
1232
1228
  for (const line of lines){
1233
1229
  if (whoisNotFoundKeywordTest(line)) {
1230
+ log$2('[whois] line %s, %O', line, whois);
1234
1231
  return false;
1235
1232
  }
1236
1233
  }
@@ -1238,7 +1235,6 @@ function walkWhois(whois) {
1238
1235
  // 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
1236
  for(const key in whois){
1240
1237
  if (Object.hasOwn(whois, key)) {
1241
- // eslint-disable-next-line sukka/no-single-return -- mutable
1242
1238
  whoisIsEmpty = false;
1243
1239
  if (key === '__raw') {
1244
1240
  continue;
@@ -1253,8 +1249,8 @@ function walkWhois(whois) {
1253
1249
  }
1254
1250
  }
1255
1251
  }
1256
- // eslint-disable-next-line sukka/no-single-return -- mutable
1257
- return whoisIsEmpty;
1252
+ log$2('[whois] %O', whois);
1253
+ return !whoisIsEmpty;
1258
1254
  }
1259
1255
 
1260
1256
  async function cacheApply(cache, key, fn) {
@@ -1284,6 +1280,8 @@ async function cacheApply(cache, key, fn) {
1284
1280
  }
1285
1281
 
1286
1282
  const log$1 = debug__default.default('domain-alive:is-registerable-domain-alive');
1283
+ const deadLog$1 = debug__default.default('domain-alive:dead-domain');
1284
+ const errorNsLog = debug__default.default('domain-alive:error:ns');
1287
1285
  const getRegisterableDomainTldtsOption = {
1288
1286
  allowIcannDomains: true,
1289
1287
  // we want to extract "github.io" out of "sukkaw.github.io" even though github.io is in the
@@ -1358,7 +1356,6 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1358
1356
  let confirmations = 0;
1359
1357
  while(attempts < maxAttempts){
1360
1358
  if (confirmations >= maxConfirmations) {
1361
- log$1('[status] %s %s', registerableDomain, true);
1362
1359
  return {
1363
1360
  registerableDomain,
1364
1361
  alive: true
@@ -1373,7 +1370,7 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1373
1370
  confirmations++;
1374
1371
  }
1375
1372
  } catch (e) {
1376
- log$1('[NS] %s error %O', domain, e);
1373
+ errorNsLog('[NS] %s error %O', domain, e);
1377
1374
  } finally{
1378
1375
  attempts++;
1379
1376
  log$1('[NS] %s %d %d/%d', domain, confirmations, attempts, maxAttempts);
@@ -1387,13 +1384,14 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1387
1384
  try {
1388
1385
  const registered = await domainHasBeenRegistered(registerableDomain, whoisOptions);
1389
1386
  log$1('[whois] %s %s', registerableDomain, registered);
1390
- log$1('[status] %s %s', registerableDomain, registered);
1387
+ if (!registered) {
1388
+ deadLog$1('[dead] %s %s', '(apex)', registerableDomain);
1389
+ }
1391
1390
  return {
1392
1391
  registerableDomain,
1393
1392
  alive: registered
1394
1393
  };
1395
1394
  } catch {
1396
- log$1('[status] %s %s', registerableDomain, whoisOptions.whoisErrorCountAsAlive ?? true);
1397
1395
  return {
1398
1396
  registerableDomain,
1399
1397
  alive: whoisOptions.whoisErrorCountAsAlive ?? true
@@ -1404,6 +1402,8 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1404
1402
  }
1405
1403
 
1406
1404
  const log = debug__default.default('domain-alive:is-domain-alive');
1405
+ const deadLog = debug__default.default('domain-alive:dead-domain');
1406
+ const errorLog = debug__default.default('domain-alive:error:dns');
1407
1407
  const sharedNullishResult = Object.freeze({
1408
1408
  registerableDomain: null,
1409
1409
  registerableDomainAlive: false,
@@ -1455,7 +1455,6 @@ function createDomainAliveChecker(options = {}) {
1455
1455
  let confirmations = 0;
1456
1456
  while(attempts < maxAttempts){
1457
1457
  if (confirmations >= maxConfirmations) {
1458
- log('[status] %s %s', domain, true);
1459
1458
  return {
1460
1459
  registerableDomain: registerableDomainAliveResult.registerableDomain,
1461
1460
  registerableDomainAlive: registerableDomainAliveResult.alive,
@@ -1471,7 +1470,12 @@ function createDomainAliveChecker(options = {}) {
1471
1470
  confirmations++;
1472
1471
  }
1473
1472
  } catch (e) {
1474
- log('[A] %s error %O', domain, e);
1473
+ if (typeof e === 'object' && e !== null) {
1474
+ Object.assign(e, {
1475
+ dns: resolve.server
1476
+ });
1477
+ }
1478
+ errorLog('[A] %s error %O', domain, e);
1475
1479
  } finally{
1476
1480
  attempts++;
1477
1481
  log('[A] %s %d %d/%d', domain, confirmations, attempts, maxAttempts);
@@ -1484,7 +1488,6 @@ function createDomainAliveChecker(options = {}) {
1484
1488
  let confirmations = 0;
1485
1489
  while(attempts < maxAttempts){
1486
1490
  if (confirmations >= maxConfirmations) {
1487
- log('[status] %s %s', domain, true);
1488
1491
  return {
1489
1492
  registerableDomain: registerableDomainAliveResult.registerableDomain,
1490
1493
  registerableDomainAlive: registerableDomainAliveResult.alive,
@@ -1500,7 +1503,12 @@ function createDomainAliveChecker(options = {}) {
1500
1503
  confirmations++;
1501
1504
  }
1502
1505
  } catch (e) {
1503
- log('[AAAA] %s error %O', domain, e);
1506
+ if (typeof e === 'object' && e !== null) {
1507
+ Object.assign(e, {
1508
+ dns: resolve.server
1509
+ });
1510
+ }
1511
+ errorLog('[AAAA] %s error %O', domain, e);
1504
1512
  } finally{
1505
1513
  attempts++;
1506
1514
  log('[AAAA] %s %d %d/%d', domain, confirmations, attempts, maxAttempts);
@@ -1508,7 +1516,7 @@ function createDomainAliveChecker(options = {}) {
1508
1516
  }
1509
1517
  }
1510
1518
  // neither A nor AAAA records found
1511
- log('[status] %s %s', domain, false);
1519
+ deadLog('[dead] %s %s', '(A/AAAA)', domain);
1512
1520
  return {
1513
1521
  registerableDomain: registerableDomainAliveResult.registerableDomain,
1514
1522
  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 rest = dns.slice(protocolIndex + 3);
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 (u.pathname === '/') {
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
  });
@@ -1044,6 +1040,7 @@ const misspelledWhoisServer = {
1044
1040
  }
1045
1041
 
1046
1042
  const log$2 = debug('domain-alive:whois');
1043
+ const errorLog$1 = debug('domain-alive:error:whois');
1047
1044
  const getIcannTldOptions = {
1048
1045
  allowIcannDomains: true,
1049
1046
  // we want to extract "github.io" out of "sukkaw.github.io" even though github.io is in the
@@ -1176,11 +1173,11 @@ const whoiserNoWhoisSymbol = Symbol('"whoiser" library returns "No WHOIS data fo
1176
1173
  throw error;
1177
1174
  }), retryOption);
1178
1175
  } catch (e) {
1179
- log$2('[whois] %s %O', registerableDomain, e);
1176
+ errorLog$1('[whois] %s %O', registerableDomain, e);
1180
1177
  return whoisErrorCountAsAlive;
1181
1178
  }
1182
1179
  if (whois === whoiserTLDNotSupportedSymbol) {
1183
- // If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's alive
1180
+ // If TLD doesn't support WHOIS/RDAP, we have no choice but to assume it's registered
1184
1181
  return true;
1185
1182
  }
1186
1183
  if (whois === whoiserNoWhoisSymbol) {
@@ -1217,12 +1214,12 @@ const whoisNotFoundKeywordTest = createRetrieKeywordFilter([
1217
1214
  // some servers (like TLD whois servers) might have cached/outdated results
1218
1215
  // we can only make sure a domain is alive once all response from all whois servers demonstrate so
1219
1216
  function walkWhois(whois) {
1220
- // eslint-disable-next-line sukka/no-single-return -- mutable
1221
1217
  let whoisIsEmpty = true;
1222
1218
  if ('__raw' in whois && typeof whois.__raw === 'string') {
1223
1219
  const lines = whois.__raw.trim().toLowerCase().replaceAll(/[\t ]+/g, ' ').split(/\r?\n/);
1224
1220
  for (const line of lines){
1225
1221
  if (whoisNotFoundKeywordTest(line)) {
1222
+ log$2('[whois] line %s, %O', line, whois);
1226
1223
  return false;
1227
1224
  }
1228
1225
  }
@@ -1230,7 +1227,6 @@ function walkWhois(whois) {
1230
1227
  // 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
1228
  for(const key in whois){
1232
1229
  if (Object.hasOwn(whois, key)) {
1233
- // eslint-disable-next-line sukka/no-single-return -- mutable
1234
1230
  whoisIsEmpty = false;
1235
1231
  if (key === '__raw') {
1236
1232
  continue;
@@ -1245,8 +1241,8 @@ function walkWhois(whois) {
1245
1241
  }
1246
1242
  }
1247
1243
  }
1248
- // eslint-disable-next-line sukka/no-single-return -- mutable
1249
- return whoisIsEmpty;
1244
+ log$2('[whois] %O', whois);
1245
+ return !whoisIsEmpty;
1250
1246
  }
1251
1247
 
1252
1248
  async function cacheApply(cache, key, fn) {
@@ -1276,6 +1272,8 @@ async function cacheApply(cache, key, fn) {
1276
1272
  }
1277
1273
 
1278
1274
  const log$1 = debug('domain-alive:is-registerable-domain-alive');
1275
+ const deadLog$1 = debug('domain-alive:dead-domain');
1276
+ const errorNsLog = debug('domain-alive:error:ns');
1279
1277
  const getRegisterableDomainTldtsOption = {
1280
1278
  allowIcannDomains: true,
1281
1279
  // we want to extract "github.io" out of "sukkaw.github.io" even though github.io is in the
@@ -1350,7 +1348,6 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1350
1348
  let confirmations = 0;
1351
1349
  while(attempts < maxAttempts){
1352
1350
  if (confirmations >= maxConfirmations) {
1353
- log$1('[status] %s %s', registerableDomain, true);
1354
1351
  return {
1355
1352
  registerableDomain,
1356
1353
  alive: true
@@ -1365,7 +1362,7 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1365
1362
  confirmations++;
1366
1363
  }
1367
1364
  } catch (e) {
1368
- log$1('[NS] %s error %O', domain, e);
1365
+ errorNsLog('[NS] %s error %O', domain, e);
1369
1366
  } finally{
1370
1367
  attempts++;
1371
1368
  log$1('[NS] %s %d %d/%d', domain, confirmations, attempts, maxAttempts);
@@ -1379,13 +1376,14 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1379
1376
  try {
1380
1377
  const registered = await domainHasBeenRegistered(registerableDomain, whoisOptions);
1381
1378
  log$1('[whois] %s %s', registerableDomain, registered);
1382
- log$1('[status] %s %s', registerableDomain, registered);
1379
+ if (!registered) {
1380
+ deadLog$1('[dead] %s %s', '(apex)', registerableDomain);
1381
+ }
1383
1382
  return {
1384
1383
  registerableDomain,
1385
1384
  alive: registered
1386
1385
  };
1387
1386
  } catch {
1388
- log$1('[status] %s %s', registerableDomain, whoisOptions.whoisErrorCountAsAlive ?? true);
1389
1387
  return {
1390
1388
  registerableDomain,
1391
1389
  alive: whoisOptions.whoisErrorCountAsAlive ?? true
@@ -1396,6 +1394,8 @@ tencentcloud.com. 86400 IN SOA ns-tel1.qq.com. webmaster.qq.com. 165111089
1396
1394
  }
1397
1395
 
1398
1396
  const log = debug('domain-alive:is-domain-alive');
1397
+ const deadLog = debug('domain-alive:dead-domain');
1398
+ const errorLog = debug('domain-alive:error:dns');
1399
1399
  const sharedNullishResult = Object.freeze({
1400
1400
  registerableDomain: null,
1401
1401
  registerableDomainAlive: false,
@@ -1447,7 +1447,6 @@ function createDomainAliveChecker(options = {}) {
1447
1447
  let confirmations = 0;
1448
1448
  while(attempts < maxAttempts){
1449
1449
  if (confirmations >= maxConfirmations) {
1450
- log('[status] %s %s', domain, true);
1451
1450
  return {
1452
1451
  registerableDomain: registerableDomainAliveResult.registerableDomain,
1453
1452
  registerableDomainAlive: registerableDomainAliveResult.alive,
@@ -1463,7 +1462,12 @@ function createDomainAliveChecker(options = {}) {
1463
1462
  confirmations++;
1464
1463
  }
1465
1464
  } catch (e) {
1466
- log('[A] %s error %O', domain, e);
1465
+ if (typeof e === 'object' && e !== null) {
1466
+ Object.assign(e, {
1467
+ dns: resolve.server
1468
+ });
1469
+ }
1470
+ errorLog('[A] %s error %O', domain, e);
1467
1471
  } finally{
1468
1472
  attempts++;
1469
1473
  log('[A] %s %d %d/%d', domain, confirmations, attempts, maxAttempts);
@@ -1476,7 +1480,6 @@ function createDomainAliveChecker(options = {}) {
1476
1480
  let confirmations = 0;
1477
1481
  while(attempts < maxAttempts){
1478
1482
  if (confirmations >= maxConfirmations) {
1479
- log('[status] %s %s', domain, true);
1480
1483
  return {
1481
1484
  registerableDomain: registerableDomainAliveResult.registerableDomain,
1482
1485
  registerableDomainAlive: registerableDomainAliveResult.alive,
@@ -1492,7 +1495,12 @@ function createDomainAliveChecker(options = {}) {
1492
1495
  confirmations++;
1493
1496
  }
1494
1497
  } catch (e) {
1495
- log('[AAAA] %s error %O', domain, e);
1498
+ if (typeof e === 'object' && e !== null) {
1499
+ Object.assign(e, {
1500
+ dns: resolve.server
1501
+ });
1502
+ }
1503
+ errorLog('[AAAA] %s error %O', domain, e);
1496
1504
  } finally{
1497
1505
  attempts++;
1498
1506
  log('[AAAA] %s %d %d/%d', domain, confirmations, attempts, maxAttempts);
@@ -1500,7 +1508,7 @@ function createDomainAliveChecker(options = {}) {
1500
1508
  }
1501
1509
  }
1502
1510
  // neither A nor AAAA records found
1503
- log('[status] %s %s', domain, false);
1511
+ deadLog('[dead] %s %s', '(A/AAAA)', domain);
1504
1512
  return {
1505
1513
  registerableDomain: registerableDomainAliveResult.registerableDomain,
1506
1514
  registerableDomainAlive: registerableDomainAliveResult.alive,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domain-alive",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
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",
@@ -31,30 +31,32 @@
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
33
  "async-retry": "^1.3.3",
34
- "debug": "^4.4.1",
35
- "dns2": "github:lsongdev/node-dns#e4fa035aca0b8eb730bde3431fbf0c60a31a09c9",
36
- "foxts": "^3.12.0",
34
+ "debug": "4.4.1",
35
+ "dns2": "github:lsongdev/node-dns#3adb7e91b3101c0e4f43ebaca3a568269ea04d11",
36
+ "foxts": "^3.13.0",
37
37
  "punycode": "^2.3.1",
38
- "tldts": "^7.0.12"
38
+ "tldts": "^7.0.14"
39
39
  },
40
40
  "devDependencies": {
41
- "@eslint-sukka/node": "^6.23.1",
41
+ "@eslint-sukka/node": "^7.0.2",
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",
45
- "@types/node": "^24.3.0",
46
+ "@types/node": "^24.3.3",
46
47
  "@types/punycode": "^2.1.4",
47
48
  "bumpp": "^10.2.3",
48
49
  "bunchee": "^6.6.0",
49
- "eslint": "^9.33.0",
50
- "eslint-config-sukka": "^6.23.1",
51
- "eslint-formatter-sukka": "^6.23.1",
50
+ "eslint": "^9.35.0",
51
+ "eslint-config-sukka": "^7.0.2",
52
+ "eslint-formatter-sukka": "^7.0.2",
52
53
  "typescript": "^5.9.2",
53
54
  "whoiser": "2.0.0-beta.8"
54
55
  },
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
  }