jsonified-whois 1.0.1
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/LICENSE +21 -0
- package/README.md +60 -0
- package/package.json +24 -0
- package/src/constants.ts +77 -0
- package/src/example/index.ts +13 -0
- package/src/index.ts +128 -0
- package/src/parser/index.ts +49 -0
- package/src/types/index.d.ts +53 -0
- package/src/utils/getFallbackData.ts +19 -0
- package/src/utils/getIpAddresses.ts +36 -0
- package/src/utils/log.ts +10 -0
- package/src/utils/normalizer.ts +8 -0
- package/src/utils/queryWhoisServer.ts +26 -0
- package/src/utils/verifyDomains.ts +15 -0
- package/tsconfig.json +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Pinghome
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# jsonified-whois
|
|
2
|
+
|
|
3
|
+
A simple, open-source WHOIS client for Node.js that returns unified data as json.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Query WHOIS information for domains
|
|
8
|
+
- Parses and normalizes WHOIS responses
|
|
9
|
+
- Supports falling back to query that has the most information
|
|
10
|
+
- Retrieves IPv4 and IPv6 addresses for domains
|
|
11
|
+
- TypeScript support
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install jsonified-whois
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
or
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
yarn add jsonified-whois
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import WhoisClient from "../index.ts";
|
|
29
|
+
import type { WhoisClientConfig } from "../types/index.js";
|
|
30
|
+
|
|
31
|
+
const config: WhoisClientConfig = {
|
|
32
|
+
url: "https://www.pinghome.io",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const whoisInstance = new WhoisClient(config);
|
|
36
|
+
|
|
37
|
+
await whoisInstance
|
|
38
|
+
.fetchData()
|
|
39
|
+
.then((res) => console.log(res))
|
|
40
|
+
.catch((error) => console.log(error));
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
See [src/example/index.ts](src/example/index.ts) for a usage example.
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `WhoisClient(options)`
|
|
48
|
+
|
|
49
|
+
- `url` (string): Domain or URL to query (required)
|
|
50
|
+
- `fallback` (boolean): Enable fallback data extraction (optional)
|
|
51
|
+
- `port` (number): WHOIS server port (default: 43)
|
|
52
|
+
- `whoisServer` (string): WHOIS server to start the query from (optional)
|
|
53
|
+
|
|
54
|
+
#### Methods
|
|
55
|
+
|
|
56
|
+
- `fetchData()`: Returns a Promise resolving to WHOIS data.
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT © 2025 Pinghome
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jsonified-whois",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A simple, open-source WHOIS client for Node.js that returns unified data as json",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"start": "node --watch --experimental-strip-types src/index.ts"
|
|
11
|
+
},
|
|
12
|
+
"repository": "https://github.com/Ping-Home/jsonified-whois",
|
|
13
|
+
"author": "ISnowFoxI",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"bugs": "https://github.com/Ping-Home/jsonified-whois/issues",
|
|
16
|
+
"homepage": "https://github.com/Ping-Home/jsonified-whois#readme",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "*",
|
|
19
|
+
"typescript": "*"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"tldts": "*"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { FieldMatchers, ParserResult } from "./types/index.js";
|
|
2
|
+
|
|
3
|
+
export const timeoutSeconds = 60;
|
|
4
|
+
|
|
5
|
+
export const ianaWhoIsServer = "whois.iana.org";
|
|
6
|
+
|
|
7
|
+
export const parserInitialData: ParserResult = {
|
|
8
|
+
createdAt: "",
|
|
9
|
+
domainName: "",
|
|
10
|
+
expiresAt: "",
|
|
11
|
+
ipAddresses: {
|
|
12
|
+
ipv4: [],
|
|
13
|
+
ipv6: [],
|
|
14
|
+
},
|
|
15
|
+
nameServers: [],
|
|
16
|
+
registrar: "",
|
|
17
|
+
updateAt: "",
|
|
18
|
+
queriedWhoisServer: "",
|
|
19
|
+
raw: "",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const ianaFieldMatchers: FieldMatchers = [
|
|
23
|
+
{
|
|
24
|
+
keywords: ["creation", "created", "registered"],
|
|
25
|
+
targetKey: "createdAt",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
keywords: ["updated", "changed", "last updated"],
|
|
29
|
+
targetKey: "updateAt",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
keywords: ["expiry", "expiration", "expires"],
|
|
33
|
+
targetKey: "expiresAt",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
keywords: ["name server", "nameserver", "nserver"],
|
|
37
|
+
targetKey: "nameServers",
|
|
38
|
+
isArray: true,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
keywords: ["whois"],
|
|
42
|
+
targetKey: "registrar",
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const gtldFiledMatchers: FieldMatchers = [
|
|
47
|
+
{
|
|
48
|
+
keywords: ["creation", "created", "registered"],
|
|
49
|
+
targetKey: "createdAt",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
keywords: ["updated", "changed", "last updated"],
|
|
53
|
+
targetKey: "updateAt",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
keywords: ["expiry", "expiration", "expires"],
|
|
57
|
+
targetKey: "expiresAt",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
keywords: [
|
|
61
|
+
"name server",
|
|
62
|
+
"nameserver",
|
|
63
|
+
"nserver",
|
|
64
|
+
"nameservers",
|
|
65
|
+
"hostname",
|
|
66
|
+
],
|
|
67
|
+
targetKey: "nameServers",
|
|
68
|
+
isArray: true,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
keywords: ["registrar whois server"],
|
|
72
|
+
targetKey: "registrar",
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
export const warnColor = "\x1b[33m";
|
|
77
|
+
export const errorColor = "\x1b[31m";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import WhoisClient from "../index.ts";
|
|
2
|
+
import type { WhoisClientConfig } from "../types/index.js";
|
|
3
|
+
|
|
4
|
+
const config: WhoisClientConfig = {
|
|
5
|
+
url: "https://www.pinghome.io",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const whoisInstance = new WhoisClient(config);
|
|
9
|
+
|
|
10
|
+
await whoisInstance
|
|
11
|
+
.fetchData()
|
|
12
|
+
.then((res) => console.log(res))
|
|
13
|
+
.catch((error) => console.log(error));
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { parser } from "./parser/index.ts";
|
|
2
|
+
import { ianaWhoIsServer, parserInitialData } from "./constants.ts";
|
|
3
|
+
import { getIpAddresses } from "./utils/getIpAddresses.ts";
|
|
4
|
+
import { verifyDomain } from "./utils/verifyDomains.ts";
|
|
5
|
+
import { queryWhoisServer } from "./utils/queryWhoisServer.ts";
|
|
6
|
+
import tldts from "tldts";
|
|
7
|
+
import { getFallbackData } from "./utils/getFallbackData.ts";
|
|
8
|
+
import type {
|
|
9
|
+
CollectWhoisChain,
|
|
10
|
+
ExistingRegistryData,
|
|
11
|
+
IpAddresses,
|
|
12
|
+
QueryResult,
|
|
13
|
+
WhoisClientConstructor,
|
|
14
|
+
WhoisResults,
|
|
15
|
+
} from "./types/index.d.ts";
|
|
16
|
+
import { logError } from "./utils/log.ts";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A client to get basic whois information
|
|
20
|
+
*/
|
|
21
|
+
class WhoisClient {
|
|
22
|
+
constructor({ url, fallback, port, whoisServer }: WhoisClientConstructor) {
|
|
23
|
+
try {
|
|
24
|
+
url && verifyDomain(url);
|
|
25
|
+
this.port = port || 43;
|
|
26
|
+
this.whoisServer = whoisServer || ianaWhoIsServer;
|
|
27
|
+
this.fallbackEnabled = fallback;
|
|
28
|
+
this.domain = tldts.getDomain(url);
|
|
29
|
+
this.hostname = tldts.getHostname(url);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
logError("Something went wrong when initializing the client \n");
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private port: number = 43;
|
|
37
|
+
private whoisServer: string = ianaWhoIsServer;
|
|
38
|
+
private ipAddresses: IpAddresses = {
|
|
39
|
+
ipv4: [],
|
|
40
|
+
ipv6: [],
|
|
41
|
+
};
|
|
42
|
+
private hostname: string = "";
|
|
43
|
+
private domain: string = "";
|
|
44
|
+
private fallbackEnabled: boolean = false;
|
|
45
|
+
private whoisResults: WhoisResults = [];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Fetch data for the instantiated domain
|
|
49
|
+
*/
|
|
50
|
+
public async fetchData() {
|
|
51
|
+
this.ipAddresses = await getIpAddresses(this.hostname);
|
|
52
|
+
const response = await this.collectWhoisChain(
|
|
53
|
+
this.domain,
|
|
54
|
+
this.whoisServer
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
let lastQuery = { ...response.at(-1) };
|
|
58
|
+
|
|
59
|
+
if (this.fallbackEnabled) {
|
|
60
|
+
lastQuery = getFallbackData(response);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
delete lastQuery.raw;
|
|
64
|
+
|
|
65
|
+
const data = {
|
|
66
|
+
queryData: response,
|
|
67
|
+
...lastQuery,
|
|
68
|
+
};
|
|
69
|
+
return JSON.stringify(data);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Queries whois servers and collects whois info recursively
|
|
74
|
+
*/
|
|
75
|
+
private async collectWhoisChain(
|
|
76
|
+
domain: string,
|
|
77
|
+
whoisServer: string
|
|
78
|
+
): CollectWhoisChain {
|
|
79
|
+
const existingRegistryData: ExistingRegistryData = this.whoisResults.find(
|
|
80
|
+
(item) => item.queriedWhoisServer === whoisServer
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (
|
|
84
|
+
existingRegistryData &&
|
|
85
|
+
(existingRegistryData.registrar.length === 0 ||
|
|
86
|
+
existingRegistryData.registrar === whoisServer)
|
|
87
|
+
) {
|
|
88
|
+
return this.whoisResults;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const response = await this.queryWhoisServer(domain, whoisServer);
|
|
92
|
+
|
|
93
|
+
this.whoisResults.push({
|
|
94
|
+
...response,
|
|
95
|
+
ipAddresses: this.ipAddresses,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!response.registrar) {
|
|
99
|
+
return this.whoisResults;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return await this.collectWhoisChain(domain, response.registrar);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Query given whois server and return parsed data with matched keys.
|
|
107
|
+
*/
|
|
108
|
+
private async queryWhoisServer(
|
|
109
|
+
domain: string,
|
|
110
|
+
whoisServer: string
|
|
111
|
+
): Promise<QueryResult> {
|
|
112
|
+
try {
|
|
113
|
+
const response = await queryWhoisServer(domain, whoisServer, this.port);
|
|
114
|
+
const isIana = whoisServer === ianaWhoIsServer;
|
|
115
|
+
const conversionResult = parser(response, isIana);
|
|
116
|
+
conversionResult.domainName = this.domain;
|
|
117
|
+
conversionResult.queriedWhoisServer = whoisServer;
|
|
118
|
+
conversionResult.raw = response;
|
|
119
|
+
conversionResult.ipAddresses = this.ipAddresses;
|
|
120
|
+
return conversionResult;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
logError(error);
|
|
123
|
+
return parserInitialData;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default WhoisClient;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
gtldFiledMatchers,
|
|
3
|
+
ianaFieldMatchers,
|
|
4
|
+
parserInitialData,
|
|
5
|
+
} from "../constants.ts";
|
|
6
|
+
import type { ParserResult } from "../types/index.d.ts";
|
|
7
|
+
import { normalizer } from "../utils/normalizer.ts";
|
|
8
|
+
|
|
9
|
+
const nameServers = "nameServers";
|
|
10
|
+
|
|
11
|
+
export const parser = (data: string, isIana: boolean) => {
|
|
12
|
+
const splitter = data.endsWith("\r\n") ? "\r\n" : "\n";
|
|
13
|
+
|
|
14
|
+
const matchers = isIana ? ianaFieldMatchers : gtldFiledMatchers;
|
|
15
|
+
const arr = data.split(">>>");
|
|
16
|
+
const responses = arr[0].split(splitter);
|
|
17
|
+
const result: ParserResult = { ...parserInitialData };
|
|
18
|
+
|
|
19
|
+
responses.forEach((item) => {
|
|
20
|
+
const [key, value] = item.split(/:(.*)/s);
|
|
21
|
+
if (!key || !value) return;
|
|
22
|
+
|
|
23
|
+
const normalizedKey = normalizer(key);
|
|
24
|
+
const trimmedValue = value.trim();
|
|
25
|
+
|
|
26
|
+
for (const matcher of matchers) {
|
|
27
|
+
const includesKeyword = matcher.keywords.some((kw) =>
|
|
28
|
+
normalizedKey.includes(kw)
|
|
29
|
+
);
|
|
30
|
+
if (!includesKeyword) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (matcher.targetKey === nameServers) {
|
|
35
|
+
const values = trimmedValue
|
|
36
|
+
.split("\r\n")
|
|
37
|
+
.map((v) => v.trim())
|
|
38
|
+
.filter(Boolean);
|
|
39
|
+
result.nameServers = [...(result.nameServers || []), ...values];
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
result[matcher.targetKey] = trimmedValue;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type IpAddresses = {
|
|
2
|
+
ipv4: Array<string>;
|
|
3
|
+
ipv6: Array<string>;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type ParserResult = {
|
|
7
|
+
domainName: string;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
updateAt: string;
|
|
10
|
+
expiresAt: string;
|
|
11
|
+
nameServers: Array<string>;
|
|
12
|
+
ipAddresses: IpAddresses;
|
|
13
|
+
registrar: string;
|
|
14
|
+
queriedWhoisServer: string;
|
|
15
|
+
raw: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type QueryResult = ParserResult;
|
|
19
|
+
|
|
20
|
+
export type Parser = (data: string, splitter: string) => ParserResult;
|
|
21
|
+
|
|
22
|
+
export type Parsers = (data: string) => ParserResult;
|
|
23
|
+
|
|
24
|
+
export type Normalizer = (str: string) => string;
|
|
25
|
+
|
|
26
|
+
export type FieldMatcher = {
|
|
27
|
+
keywords: Array<string>;
|
|
28
|
+
targetKey: string;
|
|
29
|
+
isArray?: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type FieldMatchers = Array<FieldMatcher>;
|
|
33
|
+
|
|
34
|
+
export interface WhoisClientConstructor {
|
|
35
|
+
fallback?: boolean;
|
|
36
|
+
url: string;
|
|
37
|
+
port?: number;
|
|
38
|
+
whoisServer?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type WhoisClientConfig = WhoisClientConstructor;
|
|
42
|
+
|
|
43
|
+
export type WhoisResults = Array<QueryResult>;
|
|
44
|
+
|
|
45
|
+
export type CollectWhoisChain = Promise<WhoisResults | Promise<WhoisResults>>;
|
|
46
|
+
|
|
47
|
+
export type ExistingRegistryData = QueryResult | undefined;
|
|
48
|
+
|
|
49
|
+
export type GetFallbackData = (results: WhoisResults) => QueryResult;
|
|
50
|
+
|
|
51
|
+
export type VerifyDomain = (domain: string) => void;
|
|
52
|
+
|
|
53
|
+
export type Log = (message: string) => void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GetFallbackData } from "../types/index.js";
|
|
2
|
+
|
|
3
|
+
export const getFallbackData: GetFallbackData = (results) => {
|
|
4
|
+
const reversedArr = [...results].reverse();
|
|
5
|
+
let counter = [];
|
|
6
|
+
|
|
7
|
+
for (let index in reversedArr) {
|
|
8
|
+
counter[index] = 0;
|
|
9
|
+
for (let key in reversedArr[index]) {
|
|
10
|
+
if (reversedArr[index][key]) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
counter[index]++;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const minLossIndex = counter.indexOf(Math.min(...counter));
|
|
18
|
+
return { ...reversedArr[minLossIndex] };
|
|
19
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { resolve4, resolve6 } from "dns/promises";
|
|
2
|
+
import { logWarning } from "./log.ts";
|
|
3
|
+
|
|
4
|
+
type IpResult = (domain: string) => Promise<Array<string>>;
|
|
5
|
+
|
|
6
|
+
type IpAddresses = (domain: string) => Promise<{
|
|
7
|
+
ipv4: Array<string>;
|
|
8
|
+
ipv6: Array<string>;
|
|
9
|
+
}>;
|
|
10
|
+
|
|
11
|
+
const getIpv6: IpResult = async (domain) => {
|
|
12
|
+
try {
|
|
13
|
+
return await resolve6(domain);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
logWarning("Unable to find IPv6 addresses for " + domain + "\n");
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getIpv4: IpResult = async (domain: string) => {
|
|
21
|
+
try {
|
|
22
|
+
return await resolve4(domain);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
logWarning("Unable to find IPv4 addresses for " + domain + "\n");
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const getIpAddresses: IpAddresses = async (domain) => {
|
|
30
|
+
const ipv4 = await getIpv4(domain);
|
|
31
|
+
const ipv6 = await getIpv6(domain);
|
|
32
|
+
return {
|
|
33
|
+
ipv4,
|
|
34
|
+
ipv6,
|
|
35
|
+
};
|
|
36
|
+
};
|
package/src/utils/log.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { errorColor, warnColor } from "../constants.ts";
|
|
2
|
+
import type { Log } from "../types/index.js";
|
|
3
|
+
|
|
4
|
+
export const logWarning: Log = (message) => {
|
|
5
|
+
console.warn(warnColor, message);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const logError: Log = (message) => {
|
|
9
|
+
console.error(errorColor, message);
|
|
10
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import net from "net";
|
|
2
|
+
import { timeoutSeconds } from "../constants.ts";
|
|
3
|
+
|
|
4
|
+
type GetWhoisData = (
|
|
5
|
+
domain: string,
|
|
6
|
+
whoisServer: string,
|
|
7
|
+
port: number
|
|
8
|
+
) => Promise<string>;
|
|
9
|
+
|
|
10
|
+
export const queryWhoisServer: GetWhoisData = async (
|
|
11
|
+
domain,
|
|
12
|
+
whoisServer,
|
|
13
|
+
port
|
|
14
|
+
) => {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let data = "";
|
|
17
|
+
const socket = net.createConnection({ host: whoisServer, port: port }, () =>
|
|
18
|
+
socket.write(domain + "\r\n")
|
|
19
|
+
);
|
|
20
|
+
socket.setTimeout(timeoutSeconds * 1000);
|
|
21
|
+
socket.on("data", (chunk) => (data += chunk));
|
|
22
|
+
socket.on("close", () => resolve(data));
|
|
23
|
+
socket.on("timeout", () => socket.destroy(new Error("Timeout")));
|
|
24
|
+
socket.on("error", reject);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import tldts from "tldts";
|
|
2
|
+
import type { VerifyDomain } from "../types/index.js";
|
|
3
|
+
|
|
4
|
+
export const verifyDomain: VerifyDomain = (domain) => {
|
|
5
|
+
if (!domain.length) {
|
|
6
|
+
throw new Error("Domain input is required");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const domainWithoutSuffix: string | null =
|
|
10
|
+
tldts.getDomainWithoutSuffix(domain);
|
|
11
|
+
|
|
12
|
+
if (!domainWithoutSuffix) {
|
|
13
|
+
throw new Error("Domain is not valid");
|
|
14
|
+
}
|
|
15
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "NodeNext",
|
|
4
|
+
"moduleResolution": "NodeNext",
|
|
5
|
+
"target": "ES2020",
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"noEmit": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*"]
|
|
13
|
+
}
|