@stacksjs/whois 0.58.48 → 0.58.49

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/whois",
3
3
  "type": "module",
4
- "version": "0.58.48",
4
+ "version": "0.58.49",
5
5
  "description": "Easily get whois info.",
6
6
  "author": "Chris Breuer",
7
7
  "license": "MIT",
@@ -39,7 +39,8 @@
39
39
  ],
40
40
  "files": [
41
41
  "README.md",
42
- "dist"
42
+ "dist",
43
+ "src"
43
44
  ],
44
45
  "scripts": {
45
46
  "build": "bun --bun build.ts",
package/src/index.ts ADDED
@@ -0,0 +1,499 @@
1
+ import Net from 'node:net'
2
+ import fetch from 'node-fetch'
3
+ import type { SocksClientOptions } from 'socks'
4
+ import { SocksClient } from 'socks'
5
+ import PARAMETERS from './parameters'
6
+ import SERVERS from './servers'
7
+
8
+ const IANA_CHK_URL = 'https://www.iana.org/whois?q='
9
+
10
+ /**
11
+ * Find the WhoIs server for the TLD from IANA WhoIs service. The TLD is be searched and the HTML response is parsed to extract the WhoIs server
12
+ *
13
+ * @param tld TLD of the domain
14
+ * @returns WhoIs server which hosts the information for the domains of the TLD
15
+ */
16
+ async function findWhoIsServer(tld: string): Promise<string> {
17
+ const chkURL = IANA_CHK_URL + tld
18
+
19
+ try {
20
+ const res = await fetch(chkURL)
21
+ if (res.ok) {
22
+ const body = await res.text()
23
+ const server = body.match(/whois:\s+(.*)\s+/)
24
+ if (server)
25
+ return server[1]
26
+ }
27
+ }
28
+ catch (err) {
29
+ console.error('Error in getting WhoIs server data from IANA', err)
30
+ }
31
+
32
+ return ''
33
+ }
34
+ /**
35
+ * Copy an Object with its values
36
+ *
37
+ * @param obj Object which needs to be copied
38
+ * @returns A copy of the object
39
+ */
40
+ // eslint-disable-next-line ts/no-unnecessary-type-constraint
41
+ function shallowCopy<T extends any>(obj: T): T {
42
+ if (Array.isArray(obj)) {
43
+ return obj.slice() as T // Clone the array
44
+ }
45
+ else if (typeof obj === 'object' && obj !== null) {
46
+ const copy: any = {}
47
+ for (const key in obj) {
48
+ if (Object.prototype.hasOwnProperty.call(obj, key))
49
+ copy[key] = shallowCopy(obj[key])
50
+ }
51
+ return copy as T
52
+ }
53
+ else {
54
+ return obj // For primitive values, return as is
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Get whois server of the tld from servers list
60
+ *
61
+ * @param tld TLD of the domain
62
+ * @returns WhoIs server which hosts the information for the domains of the TLD
63
+ */
64
+ function getWhoIsServer(tld: keyof typeof SERVERS): string | undefined {
65
+ return SERVERS[tld]
66
+ }
67
+
68
+ /**
69
+ * Extract TLD from domain name.
70
+ * If the TLD is in whois-servers.json file, then the TLD is returned.
71
+ * If TLD is not found within the file, then determined by taking the last element after splitting the domain name from '.'
72
+ *
73
+ * @param domain Domain name
74
+ * @returns TLD
75
+ */
76
+ function getTLD(domain: string): keyof typeof SERVERS {
77
+ let tld: keyof typeof SERVERS | null = null
78
+ let domainStr = domain
79
+
80
+ while (true) {
81
+ const domainData = domainStr.split('.')
82
+ if (domainData.length < 2)
83
+ break
84
+
85
+ const tldCheck = domainData.slice(1).join('.') as keyof typeof SERVERS
86
+ const server = SERVERS[tldCheck]
87
+ if (server) {
88
+ tld = tldCheck
89
+ break
90
+ }
91
+ domainStr = tldCheck
92
+ }
93
+
94
+ if (tld)
95
+ return tld
96
+
97
+ // eslint-disable-next-line no-console
98
+ console.debug('TLD is not found in server list. Returning last element after split as TLD!')
99
+
100
+ const domainData = domain.split('.')
101
+ return domainData[domainData.length - 1] as keyof typeof SERVERS
102
+ }
103
+
104
+ // get whois query parameters if exist on parameters.json for whois server
105
+ function getParameters(server: string): string | undefined {
106
+ return PARAMETERS[server]
107
+ }
108
+
109
+ /**
110
+ * Type of the proxy. Either SOCKS4 or SOCKS5
111
+ * @enum
112
+ */
113
+ export enum ProxyType {
114
+ /**
115
+ * SOCKS4 type of proxy
116
+ */
117
+ SOCKS4 = 0,
118
+ /**
119
+ * SOCKS5 type of proxy
120
+ */
121
+ SOCKS5 = 1,
122
+ }
123
+
124
+ /**
125
+ * Proxy related data
126
+ * @interface
127
+ *
128
+ */
129
+ export interface ProxyData {
130
+ /**
131
+ * Proxy IP
132
+ */
133
+ ip: string
134
+ /**
135
+ * Proxy port
136
+ */
137
+ port: number
138
+ /**
139
+ * Username to connect to the proxy
140
+ */
141
+ username?: string | null
142
+ /**
143
+ * Password to connect to the proxy
144
+ */
145
+ password?: string | null
146
+ /**
147
+ * {@link ProxyType}
148
+ */
149
+ type: ProxyType
150
+ }
151
+
152
+ /**
153
+ * WhoIs options
154
+ * @interface
155
+ */
156
+ export interface WhoIsOptions {
157
+ /**
158
+ * TLD of the domain. If the {@link tld} is not provided (or null), then it will be automatically determined as to the given domain name
159
+ */
160
+ tld?: string | null
161
+ /**
162
+ * The encoding type used for WhoIs server and response. By default UTF-8 is used.
163
+ */
164
+ encoding?: string | null
165
+
166
+ /** {@link ProxyData} */
167
+ proxy?: ProxyData | null
168
+ /**
169
+ * The WhoIs server to collect data from. If not provided, the server will automatically determined using the {@link tld}
170
+ */
171
+ server?: string | null
172
+ /**
173
+ * The port of the WhoIs server. By default, port 43 is used.
174
+ */
175
+ serverPort?: number | null
176
+ /**
177
+ * Which data needs to be extracted/parsed from the WhoIs response.
178
+ * An object can be passed which contains keys of the fields of the WhoIs response.
179
+ * A copy of the provided object will be returned with the values filled for the provided keys.
180
+ *
181
+ * The keys can have default value of empty string. However, if the WhoIs response has multiple values for the same field (eg: 'Domain Status'),
182
+ * then all the values can be collected by providing a default value of an Array([]).
183
+ *
184
+ * Following example shows an object used to collect 'Domain Name', 'Domain Status' (multiple values) and 'Registrar' from WhoIs response
185
+ *
186
+ * @example {'Domain Name': '', 'Domain Status': [], 'Registrar': ''}
187
+ */
188
+ parseData?: object | null
189
+ }
190
+
191
+ /**
192
+ * Response returned from whois function. Contains the raw text from WhoIs server and parsed/fornatted WhoIs data (if parsed is true)
193
+ *
194
+ * @interface
195
+ */
196
+ export interface WhoIsResponse {
197
+ /**
198
+ * Raw text response from WhoIs server
199
+ */
200
+ _raw: string
201
+ /**
202
+ * Parsed/Formatted key-value pairs of the response (if parsed is true)
203
+ */
204
+ parsedData: any | null
205
+ }
206
+
207
+ /**
208
+ * Parse collected raw WhoIs data
209
+ *
210
+ * @class
211
+ */
212
+ export class WhoIsParser {
213
+ /**
214
+ * Iterated through the complete text and returns extracted values
215
+ *
216
+ * @param rawData raw text from WhoIs server
217
+ * @param outputData Data which needs to be extracted from the raw text (key/value pairs). Keys are used to extract from raw text and values are filled.
218
+ * @returns Filled {@link outputData}
219
+ */
220
+ private static iterParse(rawData: string, outputData: any) {
221
+ let lastStr = ''
222
+ let lastField: string | null = null
223
+ let lastLetter = ''
224
+
225
+ for (let i = 0; i < rawData.length; i++) {
226
+ const letter = rawData[i]
227
+ if (letter === '\n' || (lastLetter === ':' && letter === ' ')) {
228
+ if (lastStr.trim() in outputData) {
229
+ lastField = lastStr.trim()
230
+ }
231
+ else if (lastField !== null) {
232
+ const x = lastStr.trim()
233
+ if (x !== '') {
234
+ const obj = outputData[lastField]
235
+ if (Array.isArray(obj))
236
+ obj.push(x)
237
+ else
238
+ outputData[lastField] = x
239
+
240
+ lastField = null
241
+ }
242
+ }
243
+ lastStr = ''
244
+ }
245
+ else if (letter !== ':') {
246
+ lastStr = lastStr + letter
247
+ }
248
+ lastLetter = letter as string
249
+ if (lastStr === 'Record maintained by' || lastStr === '>>>')
250
+ break
251
+ }
252
+
253
+ return outputData
254
+ }
255
+
256
+ /**
257
+ * Parse the raw WhoIs text and returns extracted values
258
+ *
259
+ * @param rawData raw text from WhoIs server
260
+ * @param outputData Data which needs to be extracted from the raw text (key/value pairs). Keys are used to extract from raw text and values are filled.
261
+ * @returns Filled {@link outputData}
262
+ */
263
+ public static parseData(rawData: string, outputData: any | null): any {
264
+ if (!outputData) {
265
+ outputData = {
266
+ 'Domain Name': '',
267
+ 'Creation Date': '',
268
+ 'Updated Date': '',
269
+ 'Registry Expiry Date': '',
270
+ 'Domain Status': [],
271
+ 'Registrar': '',
272
+ }
273
+ }
274
+
275
+ outputData = WhoIsParser.iterParse(rawData, outputData)
276
+
277
+ return outputData
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Connects to the provided {@link server}:{@link port} through TCP (through a proxy if a proxy is given), run the WhoIs query and returns the response
283
+ *
284
+ * @param domain Domain name
285
+ * @param queryOptions Query options which can be used with the specific WhoIs server to get the complete response
286
+ * @param server WhoIs server
287
+ * @param port WhoIs server port
288
+ * @param encoding Encoding used by the WhoIs server
289
+ * @param proxy {@link ProxyData}
290
+ * @returns The {string} WhoIs response for the query. Empty string is returned for errors
291
+ */
292
+ export async function tcpWhois(domain: string, queryOptions: string, server: string, port: number, encoding: string, proxy: ProxyData | null): Promise<string> {
293
+ const decoder = new TextDecoder(encoding)
294
+ const encoder = new TextEncoder()
295
+
296
+ if (!proxy) {
297
+ const socket = new Net.Socket()
298
+ return new Promise((resolve, reject) => {
299
+ try {
300
+ socket.connect({ port, host: server }, () => {
301
+ if (queryOptions !== '')
302
+ socket.write(encoder.encode(`${queryOptions} ${domain}\r\n`))
303
+ else
304
+ socket.write(encoder.encode(`${domain}\r\n`))
305
+ })
306
+
307
+ socket.on('data', (data) => {
308
+ resolve(decoder.decode(data))
309
+ })
310
+
311
+ socket.on('error', (error) => {
312
+ reject(error)
313
+ })
314
+ }
315
+ catch (e) {
316
+ reject(e)
317
+ }
318
+ })
319
+ }
320
+ else {
321
+ const options: SocksClientOptions = {
322
+ proxy: {
323
+ host: proxy.ip,
324
+ port: proxy.port,
325
+ type: proxy.type === ProxyType.SOCKS5 ? 5 : 4,
326
+ },
327
+
328
+ command: 'connect',
329
+
330
+ destination: {
331
+ host: server,
332
+ port,
333
+ },
334
+ }
335
+
336
+ if (proxy.username && proxy.password) {
337
+ options.proxy.userId = proxy.username
338
+ options.proxy.password = proxy.password
339
+ }
340
+
341
+ return new Promise((resolve, reject) => {
342
+ SocksClient.createConnection(options, (err, info) => {
343
+ if (err) {
344
+ reject(err)
345
+ }
346
+ else {
347
+ if (!info)
348
+ reject(new Error('No socket info received!'))
349
+
350
+ if (queryOptions !== '') {
351
+ info?.socket.write(
352
+ encoder.encode(`${queryOptions} ${domain}\r\n`),
353
+ )
354
+ }
355
+ else {
356
+ info?.socket.write(
357
+ encoder.encode(`${domain}\r\n`),
358
+ )
359
+ }
360
+
361
+ info?.socket.on('data', (data) => {
362
+ resolve(decoder.decode(data))
363
+ })
364
+
365
+ info?.socket.resume()
366
+ }
367
+ })
368
+ })
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Collect WhoIs data for the mentioned {@link domain}. Parse the reveived response if {@link parse} is true, accordingly.
374
+ *
375
+ * @param domain Domain name
376
+ * @param parse Whether the raw text needs to be parsed/formatted or not
377
+ * @param options {@link WhoIsOptions}
378
+ * @returns {@link WhoIsResponse} Returns a {@link WhoIsResponse} object which contains the raw text and parsed data (if parse is true)
379
+ */
380
+ export async function whois(domain: string, parse: boolean = false, options: WhoIsOptions | null = null): Promise<WhoIsResponse> {
381
+ let tld: string
382
+ let port = 43
383
+ let server = ''
384
+ let proxy: ProxyData | null
385
+ let encoding = 'utf-8'
386
+
387
+ if (!options) {
388
+ tld = getTLD(domain)
389
+ proxy = null
390
+ }
391
+ else {
392
+ tld = options.tld ? options.tld : getTLD(domain)
393
+ encoding = options.encoding ? options.encoding : 'utf-8'
394
+ proxy = options.proxy ? options.proxy : null
395
+ server = options.server ? options.server : ''
396
+ port = options.serverPort ? options.serverPort : 43
397
+ }
398
+
399
+ if (server === '') {
400
+ let serverData = getWhoIsServer(tld as keyof typeof SERVERS)
401
+ if (!serverData) {
402
+ // eslint-disable-next-line no-console
403
+ console.debug(`No WhoIs server found for TLD: ${tld}! Attempting IANA WhoIs database for server!`)
404
+ serverData = await findWhoIsServer(tld)
405
+ if (!serverData) {
406
+ // eslint-disable-next-line no-console
407
+ console.debug('WhoIs server could not be found!')
408
+ return {
409
+ _raw: '',
410
+ parsedData: null,
411
+ }
412
+ }
413
+ // eslint-disable-next-line no-console
414
+ console.debug(`WhoIs sever found for ${tld}: ${server}`)
415
+ }
416
+
417
+ server = serverData
418
+ }
419
+
420
+ const qOptions = getParameters(server)
421
+ const queryOptions = qOptions || ''
422
+
423
+ try {
424
+ const rawData = await tcpWhois(domain, queryOptions, server, port, encoding, proxy)
425
+ if (!parse) {
426
+ const parsedData = WhoIsParser.parseData(rawData, null)
427
+ return {
428
+ _raw: rawData,
429
+ parsedData,
430
+ }
431
+ }
432
+ else {
433
+ let outputData: any | null = null
434
+ if (options && options.parseData)
435
+ outputData = shallowCopy(options.parseData)
436
+
437
+ try {
438
+ const parsedData = WhoIsParser.parseData(rawData, outputData)
439
+ return {
440
+ _raw: rawData,
441
+ parsedData,
442
+ }
443
+ }
444
+ catch (err) {
445
+ console.error('Error in parsing WhoIs data!', err)
446
+ return {
447
+ _raw: rawData,
448
+ parsedData: null,
449
+ }
450
+ }
451
+ }
452
+ }
453
+ catch (err) {
454
+ return {
455
+ _raw: '',
456
+ parsedData: null,
457
+ }
458
+ }
459
+ }
460
+
461
+ export function lookup(domain: string, options: WhoIsOptions | null = null): Promise<WhoIsResponse> {
462
+ return whois(domain, true, options)
463
+ }
464
+
465
+ /**
466
+ * Collects (and parse/format if set to be true) for the provided {@link domains}. If {@link parallel} is set to be true, multiple threads will be used to batch process the domains according to {@link threads} mentioned.
467
+ * If <i>options.parsedData</i> is mentioned, then it will be used to parse <b>all</b> the responses.
468
+ * If a proxy is mentioned in {@link options}, then the proxy will be used to collect <b>all</b> the WhoIs data.
469
+ *
470
+ * @param domains Domains Names
471
+ * @param parallel Whether data should be collected parallally or not
472
+ * @param threads Batch size (for parallel processing)
473
+ * @param parse Whether the raw text needs to be parsed/formatted or not
474
+ * @param options {@link WhoIsOptions}
475
+ * @returns Array of {@link WhoIsResponse} for all the domains. Order is not guaranteed
476
+ */
477
+ export async function batchWhois(domains: string[], parallel: boolean = false, threads: number = 1, parse: boolean = false, options: WhoIsOptions | null = null): Promise<WhoIsResponse[]> {
478
+ let response: WhoIsResponse[] = []
479
+
480
+ if (parallel) {
481
+ if (threads > domains.length)
482
+ threads = domains.length
483
+
484
+ for (let i = 0; i < domains.length; i += threads) {
485
+ const batch = domains.slice(i, i + threads)
486
+ response = await Promise.all(batch.map(async (domain) => {
487
+ return await whois(domain, parse, options)
488
+ }))
489
+ }
490
+ }
491
+ else {
492
+ for (let i = 0; i < domains.length; i++) {
493
+ const res = await whois(domains[i]!, parse, options)
494
+ response.push(res)
495
+ }
496
+ }
497
+
498
+ return response
499
+ }
@@ -0,0 +1,4 @@
1
+ export default {
2
+ 'whois.denic.de': '-T dn,ace',
3
+ 'whois.nic.fr': '-V Md5.2',
4
+ }
package/src/servers.ts ADDED
@@ -0,0 +1,318 @@
1
+ export default {
2
+ 'br.com': 'whois.centralnic.net',
3
+ 'cn.com': 'whois.centralnic.net',
4
+ 'de.com': 'whois.centralnic.net',
5
+ 'eu.com': 'whois.centralnic.net',
6
+ 'gb.com': 'whois.centralnic.net',
7
+ 'gb.net': 'whois.centralnic.net',
8
+ 'gr.com': 'whois.centralnic.net',
9
+ 'hu.com': 'whois.centralnic.net',
10
+ 'in.net': 'whois.centralnic.net',
11
+ 'no.com': 'whois.centralnic.net',
12
+ 'qc.com': 'whois.centralnic.net',
13
+ 'ru.com': 'whois.centralnic.net',
14
+ 'sa.com': 'whois.centralnic.net',
15
+ 'se.com': 'whois.centralnic.net',
16
+ 'se.net': 'whois.centralnic.net',
17
+ 'uk.com': 'whois.centralnic.net',
18
+ 'uk.net': 'whois.centralnic.net',
19
+ 'us.com': 'whois.centralnic.net',
20
+ 'uy.com': 'whois.centralnic.net',
21
+ 'za.com': 'whois.centralnic.net',
22
+ 'jpn.com': 'whois.centralnic.ne',
23
+ 'web.com': 'whois.centralnic.ne',
24
+ 'com': 'whois.verisign-grs.com',
25
+ 'za.net': 'whois.za.net',
26
+ 'net': 'whois.verisign-grs.com',
27
+ 'eu.org': 'whois.eu.org',
28
+ 'za.org': 'whois.za.org',
29
+ 'org': 'whois.pir.org',
30
+ 'llyw.cymru': 'whois.nic.llyw.cymru',
31
+ 'gov.scot': 'whois.nic.gov.scot',
32
+ 'gov.wales': 'whois.nic.gov.wales',
33
+ 'edu': 'whois.educause.edu',
34
+ 'gov': 'whois.dotgov.gov',
35
+ 'int': 'whois.iana.org',
36
+ 'e164.arpa': 'whois.ripe.net',
37
+ 'arpa': 'whois.iana.org',
38
+ 'aero': 'whois.aero',
39
+ 'asia': 'whois.nic.asia',
40
+ 'biz': 'whois.nic.biz',
41
+ 'cat': 'whois.nic.cat',
42
+ 'coop': 'whois.nic.coop',
43
+ 'info': 'whois.afilias.net',
44
+ 'jobs': 'whois.nic.jobs',
45
+ 'mobi': 'whois.afilias.net',
46
+ 'museum': 'whois.nic.museum',
47
+ 'name': 'whois.nic.name',
48
+ 'post': 'whois.dotpostregistry.net',
49
+ 'pro': 'whois.nic.pro',
50
+ 'tel': 'whois.nic.tel',
51
+ 'travel': 'whois.nic.travel',
52
+ 'xxx': 'whois.nic.xxx',
53
+ 'ac': 'whois.nic.ac',
54
+ 'ae': 'whois.aeda.net.ae',
55
+ 'af': 'whois.nic.af',
56
+ 'ag': 'whois.nic.ag',
57
+ 'ai': 'whois.nic.ai',
58
+ 'am': 'whois.amnic.net',
59
+ 'ar': 'whois.nic.ar',
60
+ 'as': 'whois.nic.as',
61
+ 'priv.at': 'whois.nic.priv.at',
62
+ 'at': 'whois.nic.at',
63
+ 'au': 'whois.auda.org.au',
64
+ 'aw': 'whois.nic.aw',
65
+ 'ax': 'whois.ax',
66
+ 'be': 'whois.dns.be',
67
+ 'bf': 'whois.registre.bf',
68
+ 'bg': 'whois.register.bg',
69
+ 'bh': 'whois.nic.bh',
70
+ 'bi': 'whois1.nic.bi',
71
+ 'bj': 'whois.nic.bj',
72
+ 'bm': 'whois.afilias-srs.net',
73
+ 'bn': 'whois.bnnic.bn',
74
+ 'bo': 'whois.nic.bo',
75
+ 'br': 'whois.registro.br',
76
+ 'by': 'whois.cctld.by',
77
+ 'bw': 'whois.nic.net.bw',
78
+ 'bz': 'whois.afilias-grs.info',
79
+ 'co.ca': 'whois.co.ca',
80
+ 'ca': 'whois.cira.ca',
81
+ 'cc': 'ccwhois.verisign-grs.com',
82
+ 'cd': 'whois.nic.cd',
83
+ 'ch': 'whois.nic.ch',
84
+ 'ci': 'whois.nic.ci',
85
+ 'cl': 'whois.nic.cl',
86
+ 'cm': 'whois.netcom.cm',
87
+ 'edu.cn': 'whois.edu.cn',
88
+ 'cn': 'whois.cnnic.cn',
89
+ 'uk.co': 'whois.uk.co',
90
+ 'co': 'whois.nic.co',
91
+ 'cr': 'whois.nic.cr',
92
+ 'cx': 'whois.nic.cx',
93
+ 'cz': 'whois.nic.cz',
94
+ 'de': 'whois.denic.de',
95
+ 'dk': 'whois.dk-hostmaster.dk',
96
+ 'dm': 'whois.dmdomains.dm',
97
+ 'do': 'whois.nic.do',
98
+ 'dz': 'whois.nic.dz',
99
+ 'ec': 'whois.nic.ec',
100
+ 'ee': 'whois.tld.ee',
101
+ 'eu': 'whois.eu',
102
+ 'fi': 'whois.fi',
103
+ 'fj': 'www.whois.fj',
104
+ 'fm': 'whois.nic.fm',
105
+ 'fo': 'whois.nic.fo',
106
+ 'fr': 'whois.nic.fr',
107
+ 'gd': 'whois.nic.gd',
108
+ 'ge': 'whois.nic.ge',
109
+ 'gf': 'whois.mediaserv.net',
110
+ 'gg': 'whois.gg',
111
+ 'gh': 'whois.nic.gh',
112
+ 'gi': 'whois2.afilias-grs.net',
113
+ 'gl': 'whois.nic.gl',
114
+ 'gp': 'whois.nic.gp',
115
+ 'gq': 'whois.dominio.gq',
116
+ 'gs': 'whois.nic.gs',
117
+ 'gy': 'whois.registry.gy',
118
+ 'hk': 'whois.hkirc.hk',
119
+ 'hm': 'whois.registry.hm',
120
+ 'hn': 'whois.nic.hn',
121
+ 'hr': 'whois.dns.hr',
122
+ 'ht': 'whois.nic.ht',
123
+ 'hu': 'whois.nic.hu',
124
+ 'id': 'whois.id',
125
+ 'ie': 'whois.weare.ie',
126
+ 'il': 'whois.isoc.org.il',
127
+ 'im': 'whois.nic.im',
128
+ 'in': 'whois.registry.in',
129
+ 'io': 'whois.nic.io',
130
+ 'iq': 'whois.cmc.iq',
131
+ 'ir': 'whois.nic.ir',
132
+ 'is': 'whois.isnic.is',
133
+ 'it': 'whois.nic.it',
134
+ 'je': 'whois.je',
135
+ 'jp': 'whois.jprs.jp',
136
+ 'ke': 'whois.kenic.or.ke',
137
+ 'kg': 'whois.kg',
138
+ 'ki': 'whois.nic.ki',
139
+ 'kn': 'whois.nic.kn',
140
+ 'kr': 'whois.kr',
141
+ 'kw': 'whois.nic.kw',
142
+ 'ky': 'whois.kyregistry.ky',
143
+ 'kz': 'whois.nic.kz',
144
+ 'la': 'whois.nic.la',
145
+ 'lb': 'whois.lbdr.org.lb',
146
+ 'lc': 'whois2.afilias-grs.net',
147
+ 'li': 'whois.nic.li',
148
+ 'lk': 'whois.nic.lk',
149
+ 'ls': 'whois.nic.ls',
150
+ 'lt': 'whois.domreg.lt',
151
+ 'lu': 'whois.dns.lu',
152
+ 'lv': 'whois.nic.lv',
153
+ 'ly': 'whois.nic.ly',
154
+ 'ma': 'whois.registre.ma',
155
+ 'md': 'whois.nic.md',
156
+ 'me': 'whois.nic.me',
157
+ 'mg': 'whois.nic.mg',
158
+ 'mk': 'whois.marnet.mk',
159
+ 'ml': 'whois.dot.ml',
160
+ 'mm': 'whois.registry.gov.mm',
161
+ 'mn': 'whois.nic.mn',
162
+ 'mq': 'whois.mediaserv.net',
163
+ 'mr': 'whois.nic.mr',
164
+ 'ms': 'whois.nic.ms',
165
+ 'mt': 'whois.nic.org.mt',
166
+ 'mu': 'whois.nic.mu',
167
+ 'mw': 'whois.nic.mw',
168
+ 'mx': 'whois.mx',
169
+ 'my': 'whois.mynic.my',
170
+ 'mz': 'whois.nic.mz',
171
+ 'na': 'whois.na-nic.com.na',
172
+ 'nc': 'whois.nc',
173
+ 'nf': 'whois.nic.nf',
174
+ 'ng': 'whois.nic.net.ng',
175
+ 'nl': 'whois.domain-registry.nl',
176
+ 'no': 'whois.norid.no',
177
+ 'nu': 'whois.iis.nu',
178
+ 'nz': 'whois.irs.net.nz',
179
+ 'om': 'whois.registry.om',
180
+ 'pe': 'kero.yachay.pe',
181
+ 'pf': 'whois.registry.pf',
182
+ 'pk': 'whois.pknic.net.pk',
183
+ 'co.pl': 'whois.co.pl',
184
+ 'pl': 'whois.dns.pl',
185
+ 'pm': 'whois.nic.pm',
186
+ 'pr': 'whois.afilias-srs.net',
187
+ 'ps': 'whois.pnina.ps',
188
+ 'pt': 'whois.dns.pt',
189
+ 'pw': 'whois.nic.pw',
190
+ 'qa': 'whois.registry.qa',
191
+ 're': 'whois.nic.re',
192
+ 'ro': 'whois.rotld.ro',
193
+ 'rs': 'whois.rnids.rs',
194
+ 'ac.ru': 'whois.free.net',
195
+ 'edu.ru': 'whois.informika.ru',
196
+ 'com.ru': 'whois.flexireg.net',
197
+ 'msk.ru': 'whois.flexireg.net',
198
+ 'net.ru': 'whois.nic.net.ru',
199
+ 'nov.ru': 'whois.flexireg.net',
200
+ 'org.ru': 'whois.nic.net.ru',
201
+ 'pp.ru': 'whois.nic.net.ru',
202
+ 'spb.ru': 'whois.flexireg.net',
203
+ 'ru': 'whois.tcinet.ru',
204
+ 'rw': 'whois.ricta.org.rw',
205
+ 'sa': 'whois.nic.net.sa',
206
+ 'sb': 'whois.nic.net.sb',
207
+ 'sc': 'whois2.afilias-grs.net',
208
+ 'sd': 'whois.sdnic.sd',
209
+ 'se': 'whois.iis.se',
210
+ 'sg': 'whois.sgnic.sg',
211
+ 'sh': 'whois.nic.sh',
212
+ 'si': 'whois.register.si',
213
+ 'sk': 'whois.sk-nic.sk',
214
+ 'sl': 'whois.nic.sl',
215
+ 'sm': 'whois.nic.sm',
216
+ 'sn': 'whois.nic.sn',
217
+ 'so': 'whois.nic.so',
218
+ 'ss': 'whois.nic.ss',
219
+ 'st': 'whois.nic.st',
220
+ 'msk.su': 'whois.flexireg.net',
221
+ 'nov.su': 'whois.flexireg.net',
222
+ 'spb.su': 'whois.flexireg.net',
223
+ 'su': 'whois.tcinet.ru',
224
+ 'sx': 'whois.sx',
225
+ 'sy': 'whois.tld.sy',
226
+ 'tc': 'whois.nic.tc',
227
+ 'td': 'whois.nic.td',
228
+ 'tf': 'whois.nic.tf',
229
+ 'tg': 'whois.nic.tg',
230
+ 'th': 'whois.thnic.co.th',
231
+ 'tk': 'whois.dot.tk',
232
+ 'tl': 'whois.nic.tl',
233
+ 'tm': 'whois.nic.tm',
234
+ 'tn': 'whois.ati.tn',
235
+ 'to': 'whois.tonic.to',
236
+ 'tr': 'whois.trabis.gov.tr',
237
+ 'tv': 'whois.nic.tv',
238
+ 'tw': 'whois.twnic.net.tw',
239
+ 'tz': 'whois.tznic.or.tz',
240
+ 'biz.ua': 'whois.biz.ua',
241
+ 'co.ua': 'whois.co.ua',
242
+ 'pp.ua': 'whois.pp.ua',
243
+ 'ua': 'whois.ua',
244
+ 'ug': 'whois.co.ug',
245
+ 'ac.uk': 'whois.nic.ac.uk',
246
+ 'gov.uk': 'whois.gov.uk',
247
+ 'uk': 'whois.nic.uk',
248
+ 'fed.us': 'whois.nic.gov',
249
+ 'us': 'whois.nic.us',
250
+ 'uy': 'whois.nic.org.uy',
251
+ 'uz': 'whois.cctld.uz',
252
+ 'vc': 'whois2.afilias-grs.net',
253
+ 've': 'whois.nic.ve',
254
+ 'vg': 'whois.nic.vg',
255
+ 'vu': 'whois.dnrs.vu',
256
+ 'wf': 'whois.nic.wf',
257
+ 'ws': 'whois.website.ws',
258
+ 'yt': 'whois.nic.yt',
259
+ 'ac.za': 'whois.ac.za',
260
+ 'co.za': 'whois.registry.net.za',
261
+ 'gov.za': 'whois.gov.za',
262
+ 'net.za': 'net-whois.registry.net.za',
263
+ 'org.za': 'org-whois.registry.net.za',
264
+ 'web.za': 'web-whois.registry.net.za',
265
+ 'zm': 'whois.zicta.zm',
266
+ 'xn--2scrj9c': 'whois.registry.in',
267
+ 'xn--3e0b707e': 'whois.kr',
268
+ 'xn--3hcrj9c': 'whois.registry.in',
269
+ 'xn--45br5cyl': 'whois.registry.in',
270
+ 'xn--45brj9c': 'whois.registry.in',
271
+ 'xn--4dbrk0ce': 'whois.isoc.org.il',
272
+ 'xn--80ao21a': 'whois.nic.kz',
273
+ 'xn--90a3ac': 'whois.rnids.rs',
274
+ 'xn--90ae': 'whois.imena.bg',
275
+ 'xn--90ais': 'whois.cctld.by',
276
+ 'xn--clchc0ea0b2g2a9gcd': 'whois.sgnic.sg',
277
+ 'xn--d1alf': 'whois.marnet.mk',
278
+ 'xn--e1a4c': 'whois.eu',
279
+ 'xn--fiqs8s': 'cwhois.cnnic.cn',
280
+ 'xn--fiqz9s': 'cwhois.cnnic.cn',
281
+ 'xn--fpcrj9c3d': 'whois.registry.in',
282
+ 'xn--fzc2c9e2c': 'whois.nic.lk',
283
+ 'xn--gecrj9c': 'whois.registry.in',
284
+ 'xn--h2breg3eve': 'whois.registry.in',
285
+ 'xn--h2brj9c8c': 'whois.registry.in',
286
+ 'xn--h2brj9c': 'whois.registry.in',
287
+ 'xn--j1amh': 'whois.dotukr.com',
288
+ 'xn--j6w193g': 'whois.hkirc.hk',
289
+ 'xn--kprw13d': 'whois.twnic.net.tw',
290
+ 'xn--kpry57d': 'whois.twnic.net.tw',
291
+ 'xn--lgbbat1ad8j': 'whois.nic.dz',
292
+ 'xn--mgb9awbf': 'whois.registry.om',
293
+ 'xn--mgba3a4f16a': 'whois.nic.ir',
294
+ 'xn--mgbaam7a8h': 'whois.aeda.net.ae',
295
+ 'xn--mgbah1a3hjkrd': 'whois.nic.mr',
296
+ 'xn--mgbbh1a71e': 'whois.registry.in',
297
+ 'xn--mgbbh1a': 'whois.registry.in',
298
+ 'xn--mgberp4a5d4ar': 'whois.nic.net.sa',
299
+ 'xn--mgbgu82a': 'whois.registry.in',
300
+ 'xn--mgbtx2b': 'whois.cmc.iq',
301
+ 'xn--mgbx4cd0ab': 'whois.mynic.my',
302
+ 'xn--node': 'whois.itdc.ge',
303
+ 'xn--o3cw4h': 'whois.thnic.co.th',
304
+ 'xn--ogbpf8fl': 'whois.tld.sy',
305
+ 'xn--p1ai': 'whois.tcinet.ru',
306
+ 'xn--pgbs0dh': 'whois.ati.tn',
307
+ 'xn--q7ce6a': 'whois.nic.la',
308
+ 'xn--qxa6a': 'whois.eu',
309
+ 'xn--rvc1e0am3e': 'whois.registry.in',
310
+ 'xn--s9brj9c': 'whois.registry.in',
311
+ 'xn--wgbh1c': 'whois.dotmasr.eg',
312
+ 'xn--wgbl6a': 'whois.registry.qa',
313
+ 'xn--xkc2al3hye2a': 'whois.nic.lk',
314
+ 'xn--xkc2dl3a5ee0h': 'whois.registry.in',
315
+ 'xn--y9a3aq': 'whois.amnic.net',
316
+ 'xn--yfro4i67o': 'whois.sgnic.sg',
317
+ 'xn--ygbi2ammx': 'whois.pnina.ps',
318
+ }
package/src/test.ts ADDED
@@ -0,0 +1,5 @@
1
+ // import { whois } from './index'
2
+
3
+ // const r = (await whois('stacksjs.org', true)).parsedData.Registrar
4
+
5
+ // console.log(r)