@chez14/rdap-sdk 0.1.1-5 → 0.1.1-8

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/README.md CHANGED
@@ -51,7 +51,7 @@ const asn = await client.autnum(174);
51
51
  console.log(asn.name);
52
52
 
53
53
  // Use custom base domain (default is www.rdap.net)
54
- const customClient = new RdapOrgClient({
54
+ const customClient = new RdapClient({
55
55
  baseDomain: 'custom.rdap.example.com'
56
56
  });
57
57
  ```
@@ -85,7 +85,7 @@ class CustomFetcher implements Fetcher {
85
85
  }
86
86
 
87
87
  // Use your custom fetcher
88
- const client = new RdapOrgClient({
88
+ const client = new RdapClient({
89
89
  fetcher: new CustomFetcher('MyApp/1.0 (https://example.com)'),
90
90
  });
91
91
  ```
package/dist/index.d.ts CHANGED
@@ -1,55 +1,165 @@
1
- /**
2
- * Base response interface for RDAP queries
3
- */
4
- interface RdapResponse {
5
- rdapConformance: string[];
6
- notices?: Array<{
7
- title?: string;
8
- description: string[];
9
- links?: Array<{
10
- value: string;
11
- rel: string;
12
- href: string;
13
- type?: string;
14
- }>;
15
- }>;
1
+ interface RdapLink {
2
+ value: string;
3
+ rel: string;
4
+ href: string;
5
+ hreflang?: string[];
6
+ type?: string;
7
+ media?: string;
8
+ title?: string;
16
9
  }
17
- /**
18
- * Domain response interface
19
- */
20
- interface DomainResponse extends RdapResponse {
10
+ interface RdapEvent {
11
+ eventAction: string;
12
+ eventActor?: string;
13
+ eventDate: string;
14
+ links?: RdapLink[];
15
+ }
16
+ interface RdapPublicID {
17
+ type: string;
18
+ identifier: string;
19
+ }
20
+ type RdapStatus = 'validated' | 'renew prohibited' | 'update prohibited' | 'transfer prohibited' | 'delete prohibited' | 'proxy' | 'private' | 'removed' | 'obscured' | 'associated' | 'active' | 'inactive' | 'locked' | 'pending create' | 'pending renew' | 'pending transfer' | 'pending update' | 'pending delete';
21
+ type RdapNoticeAndRemarkTypes = 'result set truncated due to authorization' | 'result set truncated due to excessive load' | 'result set truncated due to unexplainable reasons' | 'object truncated due to authorization' | 'object truncated due to excessive load' | 'object truncated due to unexplainable reasons';
22
+ interface RdapRemark {
23
+ title?: string;
24
+ type?: RdapNoticeAndRemarkTypes;
25
+ description: string[];
26
+ links?: RdapLink[];
27
+ }
28
+ interface RdapDsData {
29
+ keyTag?: number;
30
+ algorithm?: number;
31
+ digest?: string;
32
+ digestType?: string;
33
+ events?: RdapEvent[];
34
+ links?: RdapLink[];
35
+ }
36
+ interface RdapKeyData {
37
+ flags?: number;
38
+ protocol?: number;
39
+ publicKey?: string;
40
+ algorithm?: number;
41
+ events?: RdapEvent[];
42
+ links?: RdapLink[];
43
+ }
44
+ interface RdapSecureDNS {
45
+ zoneSigned?: boolean;
46
+ delegationSigned?: boolean;
47
+ maxSigLife?: number;
48
+ dsData?: RdapDsData[];
49
+ keyData?: RdapKeyData[];
50
+ }
51
+ type RdapNotice = RdapRemark;
52
+ type RdapObjectClass = RdapEntityObjectClass | RdapNameserverObjectClass | RdapDomainObjectClass;
53
+ interface RdapEntityObjectClass {
54
+ objectClassName: 'entity';
55
+ handle?: string;
56
+ vcardArray?: any[];
57
+ roles?: string[];
58
+ publicIds?: RdapPublicID[];
59
+ entities?: RdapEntityObjectClass[];
60
+ remarks?: RdapRemark[];
61
+ links?: RdapLink[];
62
+ events?: RdapEvent[];
63
+ asEventActor?: Omit<RdapEvent, 'eventActor'>[];
64
+ status?: RdapStatus[];
65
+ port43?: string;
66
+ networks?: RdapIPNetworkObjectClass[];
67
+ autnums?: RdapAutonomousSystemNumberObjectClass[];
68
+ }
69
+ interface RdapNameserverObjectClass {
70
+ objectClassName: 'nameserver';
71
+ handle?: string;
72
+ ldhName?: string;
73
+ unicodeName?: string;
74
+ ipAddresses?: {
75
+ v6: string[];
76
+ v4: string[];
77
+ };
78
+ entities?: RdapEntityObjectClass[];
79
+ status?: RdapStatus[];
80
+ remarks?: RdapRemark[];
81
+ links?: RdapLink[];
82
+ port43?: string;
83
+ events?: RdapEvent[];
84
+ }
85
+ interface RdapDomainObjectClass {
21
86
  objectClassName: 'domain';
22
87
  handle?: string;
23
- ldhName: string;
24
- links: Array<{
25
- rel: string;
26
- href: string;
27
- type?: string;
28
- }>;
88
+ ldhName?: string;
89
+ unicodeName?: string;
90
+ variants: {
91
+ relation: string[];
92
+ idnTable: string;
93
+ variantName: {
94
+ ldhName: string;
95
+ unicodeName: string;
96
+ }[];
97
+ }[];
98
+ nameservers: RdapNameserverObjectClass[];
99
+ secureDNS: RdapSecureDNS;
100
+ entities?: RdapEntityObjectClass[];
101
+ status?: RdapStatus[];
102
+ publicIds?: RdapPublicID[];
103
+ remarks: RdapRemark[];
104
+ links?: RdapLink[];
105
+ port43?: string;
106
+ events?: RdapEvent[];
107
+ network?: RdapIPNetworkObjectClass;
29
108
  }
30
- /**
31
- * IP Network response interface
32
- */
33
- interface IpNetworkResponse extends RdapResponse {
109
+ interface RdapIPNetworkObjectClass {
34
110
  objectClassName: 'ip network';
35
- handle: string;
36
- startAddress: string;
37
- endAddress: string;
38
- ipVersion: string;
111
+ handle?: string;
112
+ startAddress?: string;
113
+ endAddress?: string;
114
+ ipVersion?: 'v4' | 'v6';
39
115
  name?: string;
40
116
  type?: string;
117
+ country?: string;
118
+ parentHandle?: string;
119
+ status?: RdapStatus[];
120
+ entities?: RdapEntityObjectClass[];
121
+ remarks: RdapRemark[];
122
+ links?: RdapLink[];
123
+ port43?: string;
124
+ events?: RdapEvent[];
41
125
  }
42
- /**
43
- * Autonomous System Number response interface
44
- */
45
- interface AutonomousSystemResponse extends RdapResponse {
126
+ interface RdapAutonomousSystemNumberObjectClass {
46
127
  objectClassName: 'autnum';
47
- handle: string;
48
- startAutnum: number;
49
- endAutnum: number;
128
+ handle?: string;
129
+ startAutnum?: string;
130
+ endAutnum?: string;
50
131
  name?: string;
51
132
  type?: string;
133
+ status?: RdapStatus[];
134
+ country?: string;
135
+ entities?: RdapEntityObjectClass[];
136
+ remarks: RdapRemark[];
137
+ links?: RdapLink[];
138
+ port43?: string;
139
+ events?: RdapEvent[];
140
+ }
141
+ interface RdapDomainSuccessResponse extends RdapDomainObjectClass {
142
+ rdapConformance: string[];
52
143
  }
144
+ interface RdapIpSuccessResponse extends RdapIPNetworkObjectClass {
145
+ rdapConformance: string[];
146
+ }
147
+ interface RdapAutnumSuccessResponse extends RdapAutonomousSystemNumberObjectClass {
148
+ rdapConformance: string[];
149
+ }
150
+ interface RdapHelpSuccessResponse {
151
+ rdapConformance: string[];
152
+ notices?: RdapNotice[];
153
+ }
154
+ interface RdapErrorResponse {
155
+ errorCode: number;
156
+ title?: string;
157
+ description?: string[];
158
+ }
159
+ type RdapDomainResponse = RdapErrorResponse & RdapDomainSuccessResponse;
160
+ type RdapIpResponse = RdapErrorResponse & RdapIpSuccessResponse;
161
+ type RdapAutnumResponse = RdapErrorResponse & RdapAutnumSuccessResponse;
162
+ type RdapHelpResponse = RdapErrorResponse & RdapHelpSuccessResponse;
53
163
 
54
164
  /**
55
165
  * HTTP methods supported by the fetcher
@@ -71,6 +181,7 @@ interface FetchResponse<T = unknown> {
71
181
  status: number;
72
182
  data: T;
73
183
  headers: Headers;
184
+ url: string;
74
185
  }
75
186
  /**
76
187
  * Interface for the fetcher implementation
@@ -85,14 +196,14 @@ declare class DefaultFetcher implements Fetcher {
85
196
  fetch<TBody = unknown, TResponse = unknown>({ method, url, body, headers, }: FetchOptions<TBody>): Promise<FetchResponse<TResponse>>;
86
197
  }
87
198
 
88
- interface RdapOrgClientOptions {
199
+ interface RdapClientOptions {
89
200
  fetcher?: Fetcher;
90
201
  baseDomain?: string;
91
202
  }
92
203
  declare class RdapClient {
93
204
  private readonly fetcher;
94
205
  private readonly baseDomain;
95
- constructor(options?: RdapOrgClientOptions);
206
+ constructor(options?: RdapClientOptions);
96
207
  /**
97
208
  * Convert domain to punycode if needed
98
209
  */
@@ -103,37 +214,37 @@ declare class RdapClient {
103
214
  * @returns Domain information
104
215
  * @example
105
216
  * ```typescript
106
- * const client = new RdapOrgClient();
217
+ * const client = new RdapClient();
107
218
  * const domain = await client.domain('example.com');
108
219
  * // IDN support
109
220
  * const idn = await client.domain('münchen.de');
110
221
  * ```
111
222
  */
112
- domain(domain: string): Promise<DomainResponse>;
223
+ domain(domain: string): Promise<RdapDomainResponse>;
113
224
  /**
114
225
  * Query IP address or network information
115
226
  * @param ip IP address or CIDR notation
116
227
  * @returns IP network information
117
228
  * @example
118
229
  * ```typescript
119
- * const client = new RdapOrgClient();
230
+ * const client = new RdapClient();
120
231
  * const ip = await client.ip('8.8.8.8');
121
232
  * // or with CIDR notation
122
233
  * const network = await client.ip('2001:db8::1/128');
123
234
  * ```
124
235
  */
125
- ip(ip: string): Promise<IpNetworkResponse>;
236
+ ip(ip: string): Promise<RdapIpResponse>;
126
237
  /**
127
238
  * Query Autonomous System Number information
128
239
  * @param asn Autonomous System Number
129
240
  * @returns ASN information
130
241
  * @example
131
242
  * ```typescript
132
- * const client = new RdapOrgClient();
243
+ * const client = new RdapClient();
133
244
  * const asn = await client.autnum(174);
134
245
  * ```
135
246
  */
136
- autnum(asn: number): Promise<AutonomousSystemResponse>;
247
+ autnum(asn: number): Promise<RdapAutnumResponse>;
137
248
  }
138
249
 
139
- export { type AutonomousSystemResponse, DefaultFetcher, type DomainResponse, type FetchOptions, type FetchResponse, type Fetcher, type HttpMethod, type IpNetworkResponse, RdapClient, type RdapOrgClientOptions, type RdapResponse };
250
+ export { DefaultFetcher, type FetchOptions, type FetchResponse, type Fetcher, type HttpMethod, type RdapAutnumResponse, type RdapAutnumSuccessResponse, type RdapAutonomousSystemNumberObjectClass, RdapClient, type RdapClientOptions, type RdapDomainObjectClass, type RdapDomainResponse, type RdapDomainSuccessResponse, type RdapDsData, type RdapEntityObjectClass, type RdapErrorResponse, type RdapEvent, type RdapHelpResponse, type RdapHelpSuccessResponse, type RdapIPNetworkObjectClass, type RdapIpResponse, type RdapIpSuccessResponse, type RdapKeyData, type RdapLink, type RdapNameserverObjectClass, type RdapNotice, type RdapNoticeAndRemarkTypes, type RdapObjectClass, type RdapPublicID, type RdapRemark, type RdapSecureDNS, type RdapStatus };
package/dist/index.js CHANGED
@@ -27,11 +27,20 @@ var DefaultFetcher = class {
27
27
  return {
28
28
  status: response.status,
29
29
  data,
30
- headers: response.headers
30
+ headers: response.headers,
31
+ url: response.url
31
32
  };
32
33
  }
33
34
  };
34
35
 
36
+ // src/utils/throwables.ts
37
+ var RdapNotFoundError = class extends Error {
38
+ constructor(message) {
39
+ super(message);
40
+ this.name = "RdapNotFoundError";
41
+ }
42
+ };
43
+
35
44
  // src/client.ts
36
45
  var RdapClient = class {
37
46
  constructor(options = {}) {
@@ -60,7 +69,7 @@ var RdapClient = class {
60
69
  * @returns Domain information
61
70
  * @example
62
71
  * ```typescript
63
- * const client = new RdapOrgClient();
72
+ * const client = new RdapClient();
64
73
  * const domain = await client.domain('example.com');
65
74
  * // IDN support
66
75
  * const idn = await client.domain('münchen.de');
@@ -68,10 +77,14 @@ var RdapClient = class {
68
77
  */
69
78
  async domain(domain) {
70
79
  const punyDomain = this.prepareDomain(domain);
80
+ const url = `https://${this.baseDomain}/domain/${encodeURIComponent(punyDomain)}`;
71
81
  const response = await this.fetcher.fetch({
72
82
  method: "GET",
73
- url: `https://${this.baseDomain}/domain/${encodeURIComponent(punyDomain)}`
83
+ url
74
84
  });
85
+ if (response.status === 404 && response.url === url) {
86
+ throw new RdapNotFoundError(`Domain ${domain} has no RDAP server for its TLD`);
87
+ }
75
88
  return response.data;
76
89
  }
77
90
  /**
@@ -80,7 +93,7 @@ var RdapClient = class {
80
93
  * @returns IP network information
81
94
  * @example
82
95
  * ```typescript
83
- * const client = new RdapOrgClient();
96
+ * const client = new RdapClient();
84
97
  * const ip = await client.ip('8.8.8.8');
85
98
  * // or with CIDR notation
86
99
  * const network = await client.ip('2001:db8::1/128');
@@ -99,7 +112,7 @@ var RdapClient = class {
99
112
  * @returns ASN information
100
113
  * @example
101
114
  * ```typescript
102
- * const client = new RdapOrgClient();
115
+ * const client = new RdapClient();
103
116
  * const asn = await client.autnum(174);
104
117
  * ```
105
118
  */
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/fetcher.ts","../src/client.ts"],"sourcesContent":["/**\n * HTTP methods supported by the fetcher\n */\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\n/**\n * Options for the fetch request\n */\nexport interface FetchOptions<T = unknown> {\n method: HttpMethod;\n url: string;\n body?: T;\n headers?: Record<string, string>;\n}\n\n/**\n * Response from the fetch request\n */\nexport interface FetchResponse<T = unknown> {\n status: number;\n data: T;\n headers: Headers;\n}\n\n/**\n * Interface for the fetcher implementation\n */\nexport interface Fetcher {\n fetch<TBody = unknown, TResponse = unknown>(\n options: FetchOptions<TBody>,\n ): Promise<FetchResponse<TResponse>>;\n}\n\n/**\n * Default fetcher implementation using node-fetch\n */\nexport class DefaultFetcher implements Fetcher {\n async fetch<TBody = unknown, TResponse = unknown>({\n method,\n url,\n body,\n headers = {},\n }: FetchOptions<TBody>): Promise<FetchResponse<TResponse>> {\n const requestUrl = new URL(url);\n\n // For GET requests, convert body to query parameters\n if (method === 'GET' && body) {\n Object.entries(body as Record<string, string>).forEach(([key, value]) => {\n requestUrl.searchParams.append(key, value);\n });\n }\n\n const requestInit: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n };\n\n // Add body for non-GET requests\n if (method !== 'GET' && body) {\n requestInit.body = JSON.stringify(body);\n }\n\n const response = await fetch(requestUrl, requestInit);\n const data = (await response.json()) as TResponse;\n\n return {\n status: response.status,\n data,\n headers: response.headers,\n };\n }\n}\n","import { AutonomousSystemResponse, DomainResponse, IpNetworkResponse } from './types';\nimport { DefaultFetcher, Fetcher } from './utils/fetcher';\n\nexport interface RdapOrgClientOptions {\n fetcher?: Fetcher;\n baseDomain?: string;\n}\n\nexport class RdapClient {\n private readonly fetcher: Fetcher;\n private readonly baseDomain: string;\n\n constructor(options: RdapOrgClientOptions = {}) {\n this.fetcher = options.fetcher ?? new DefaultFetcher();\n this.baseDomain = options.baseDomain ?? 'www.rdap.net';\n }\n\n /**\n * Convert domain to punycode if needed\n */\n private prepareDomain(domain: string): string {\n return domain\n .toLowerCase()\n .split('.')\n .map((part) => {\n try {\n if (part.includes('xn--')) {\n return part;\n }\n // Use URL API to handle IDN conversion\n const url = new URL(`https://${part}`);\n return url.hostname.startsWith('xn--') ? url.hostname : part;\n } catch {\n return part;\n }\n })\n .join('.');\n }\n\n /**\n * Query domain information\n * @param domain Domain name to query (supports IDN/punycode)\n * @returns Domain information\n * @example\n * ```typescript\n * const client = new RdapOrgClient();\n * const domain = await client.domain('example.com');\n * // IDN support\n * const idn = await client.domain('münchen.de');\n * ```\n */\n async domain(domain: string): Promise<DomainResponse> {\n const punyDomain = this.prepareDomain(domain);\n const response = await this.fetcher.fetch<never, DomainResponse>({\n method: 'GET',\n url: `https://${this.baseDomain}/domain/${encodeURIComponent(punyDomain)}`,\n });\n\n return response.data;\n }\n\n /**\n * Query IP address or network information\n * @param ip IP address or CIDR notation\n * @returns IP network information\n * @example\n * ```typescript\n * const client = new RdapOrgClient();\n * const ip = await client.ip('8.8.8.8');\n * // or with CIDR notation\n * const network = await client.ip('2001:db8::1/128');\n * ```\n */\n async ip(ip: string): Promise<IpNetworkResponse> {\n const response = await this.fetcher.fetch<never, IpNetworkResponse>({\n method: 'GET',\n url: `https://${this.baseDomain}/ip/${encodeURIComponent(ip)}`,\n });\n\n return response.data;\n }\n\n /**\n * Query Autonomous System Number information\n * @param asn Autonomous System Number\n * @returns ASN information\n * @example\n * ```typescript\n * const client = new RdapOrgClient();\n * const asn = await client.autnum(174);\n * ```\n */\n async autnum(asn: number): Promise<AutonomousSystemResponse> {\n const response = await this.fetcher.fetch<never, AutonomousSystemResponse>({\n method: 'GET',\n url: `https://${this.baseDomain}/autnum/${asn}`,\n });\n\n return response.data;\n }\n}\n"],"mappings":";AAoCO,IAAM,iBAAN,MAAwC;AAAA,EAC7C,MAAM,MAA4C;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC;AAAA,EACb,GAA2D;AACzD,UAAM,aAAa,IAAI,IAAI,GAAG;AAG9B,QAAI,WAAW,SAAS,MAAM;AAC5B,aAAO,QAAQ,IAA8B,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACvE,mBAAW,aAAa,OAAO,KAAK,KAAK;AAAA,MAC3C,CAAC;AAAA,IACH;AAEA,UAAM,cAA2B;AAAA,MAC/B;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAG;AAAA,MACL;AAAA,IACF;AAGA,QAAI,WAAW,SAAS,MAAM;AAC5B,kBAAY,OAAO,KAAK,UAAU,IAAI;AAAA,IACxC;AAEA,UAAM,WAAW,MAAM,MAAM,YAAY,WAAW;AACpD,UAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,WAAO;AAAA,MACL,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,SAAS,SAAS;AAAA,IACpB;AAAA,EACF;AACF;;;AClEO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAAY,UAAgC,CAAC,GAAG;AAC9C,SAAK,UAAU,QAAQ,WAAW,IAAI,eAAe;AACrD,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,QAAwB;AAC5C,WAAO,OACJ,YAAY,EACZ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS;AACb,UAAI;AACF,YAAI,KAAK,SAAS,MAAM,GAAG;AACzB,iBAAO;AAAA,QACT;AAEA,cAAM,MAAM,IAAI,IAAI,WAAW,IAAI,EAAE;AACrC,eAAO,IAAI,SAAS,WAAW,MAAM,IAAI,IAAI,WAAW;AAAA,MAC1D,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC,EACA,KAAK,GAAG;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OAAO,QAAyC;AACpD,UAAM,aAAa,KAAK,cAAc,MAAM;AAC5C,UAAM,WAAW,MAAM,KAAK,QAAQ,MAA6B;AAAA,MAC/D,QAAQ;AAAA,MACR,KAAK,WAAW,KAAK,UAAU,WAAW,mBAAmB,UAAU,CAAC;AAAA,IAC1E,CAAC;AAED,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,GAAG,IAAwC;AAC/C,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAgC;AAAA,MAClE,QAAQ;AAAA,MACR,KAAK,WAAW,KAAK,UAAU,OAAO,mBAAmB,EAAE,CAAC;AAAA,IAC9D,CAAC;AAED,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,OAAO,KAAgD;AAC3D,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAuC;AAAA,MACzE,QAAQ;AAAA,MACR,KAAK,WAAW,KAAK,UAAU,WAAW,GAAG;AAAA,IAC/C,CAAC;AAED,WAAO,SAAS;AAAA,EAClB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/utils/fetcher.ts","../src/utils/throwables.ts","../src/client.ts"],"sourcesContent":["/**\n * HTTP methods supported by the fetcher\n */\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\n/**\n * Options for the fetch request\n */\nexport interface FetchOptions<T = unknown> {\n method: HttpMethod;\n url: string;\n body?: T;\n headers?: Record<string, string>;\n}\n\n/**\n * Response from the fetch request\n */\nexport interface FetchResponse<T = unknown> {\n status: number;\n data: T;\n headers: Headers;\n url: string;\n}\n\n/**\n * Interface for the fetcher implementation\n */\nexport interface Fetcher {\n fetch<TBody = unknown, TResponse = unknown>(\n options: FetchOptions<TBody>,\n ): Promise<FetchResponse<TResponse>>;\n}\n\n/**\n * Default fetcher implementation using node-fetch\n */\nexport class DefaultFetcher implements Fetcher {\n async fetch<TBody = unknown, TResponse = unknown>({\n method,\n url,\n body,\n headers = {},\n }: FetchOptions<TBody>): Promise<FetchResponse<TResponse>> {\n const requestUrl = new URL(url);\n\n // For GET requests, convert body to query parameters\n if (method === 'GET' && body) {\n Object.entries(body as Record<string, string>).forEach(([key, value]) => {\n requestUrl.searchParams.append(key, value);\n });\n }\n\n const requestInit: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n };\n\n // Add body for non-GET requests\n if (method !== 'GET' && body) {\n requestInit.body = JSON.stringify(body);\n }\n\n const response = await fetch(requestUrl, requestInit);\n const data = (await response.json()) as TResponse;\n\n return {\n status: response.status,\n data,\n headers: response.headers,\n url: response.url,\n };\n }\n}\n","export class RdapNotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RdapNotFoundError';\n }\n}\n","import { RdapAutnumResponse, RdapDomainResponse, RdapIpResponse } from './types';\nimport { DefaultFetcher, Fetcher } from './utils/fetcher';\nimport { RdapNotFoundError } from './utils/throwables';\n\nexport interface RdapClientOptions {\n fetcher?: Fetcher;\n baseDomain?: string;\n}\n\nexport class RdapClient {\n private readonly fetcher: Fetcher;\n private readonly baseDomain: string;\n\n constructor(options: RdapClientOptions = {}) {\n this.fetcher = options.fetcher ?? new DefaultFetcher();\n this.baseDomain = options.baseDomain ?? 'www.rdap.net';\n }\n\n /**\n * Convert domain to punycode if needed\n */\n private prepareDomain(domain: string): string {\n return domain\n .toLowerCase()\n .split('.')\n .map((part) => {\n try {\n if (part.includes('xn--')) {\n return part;\n }\n // Use URL API to handle IDN conversion\n const url = new URL(`https://${part}`);\n return url.hostname.startsWith('xn--') ? url.hostname : part;\n } catch {\n return part;\n }\n })\n .join('.');\n }\n\n /**\n * Query domain information\n * @param domain Domain name to query (supports IDN/punycode)\n * @returns Domain information\n * @example\n * ```typescript\n * const client = new RdapClient();\n * const domain = await client.domain('example.com');\n * // IDN support\n * const idn = await client.domain('münchen.de');\n * ```\n */\n async domain(domain: string): Promise<RdapDomainResponse> {\n const punyDomain = this.prepareDomain(domain);\n const url = `https://${this.baseDomain}/domain/${encodeURIComponent(punyDomain)}`;\n const response = await this.fetcher.fetch<never, RdapDomainResponse>({\n method: 'GET',\n url,\n });\n\n if (response.status === 404 && response.url === url) {\n throw new RdapNotFoundError(`Domain ${domain} has no RDAP server for its TLD`);\n }\n\n return response.data;\n }\n\n /**\n * Query IP address or network information\n * @param ip IP address or CIDR notation\n * @returns IP network information\n * @example\n * ```typescript\n * const client = new RdapClient();\n * const ip = await client.ip('8.8.8.8');\n * // or with CIDR notation\n * const network = await client.ip('2001:db8::1/128');\n * ```\n */\n async ip(ip: string): Promise<RdapIpResponse> {\n const response = await this.fetcher.fetch<never, RdapIpResponse>({\n method: 'GET',\n url: `https://${this.baseDomain}/ip/${encodeURIComponent(ip)}`,\n });\n\n return response.data;\n }\n\n /**\n * Query Autonomous System Number information\n * @param asn Autonomous System Number\n * @returns ASN information\n * @example\n * ```typescript\n * const client = new RdapClient();\n * const asn = await client.autnum(174);\n * ```\n */\n async autnum(asn: number): Promise<RdapAutnumResponse> {\n const response = await this.fetcher.fetch<never, RdapAutnumResponse>({\n method: 'GET',\n url: `https://${this.baseDomain}/autnum/${asn}`,\n });\n\n return response.data;\n }\n}\n"],"mappings":";AAqCO,IAAM,iBAAN,MAAwC;AAAA,EAC7C,MAAM,MAA4C;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC;AAAA,EACb,GAA2D;AACzD,UAAM,aAAa,IAAI,IAAI,GAAG;AAG9B,QAAI,WAAW,SAAS,MAAM;AAC5B,aAAO,QAAQ,IAA8B,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACvE,mBAAW,aAAa,OAAO,KAAK,KAAK;AAAA,MAC3C,CAAC;AAAA,IACH;AAEA,UAAM,cAA2B;AAAA,MAC/B;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAG;AAAA,MACL;AAAA,IACF;AAGA,QAAI,WAAW,SAAS,MAAM;AAC5B,kBAAY,OAAO,KAAK,UAAU,IAAI;AAAA,IACxC;AAEA,UAAM,WAAW,MAAM,MAAM,YAAY,WAAW;AACpD,UAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,WAAO;AAAA,MACL,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,SAAS,SAAS;AAAA,MAClB,KAAK,SAAS;AAAA,IAChB;AAAA,EACF;AACF;;;AC5EO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACIO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,UAAU,QAAQ,WAAW,IAAI,eAAe;AACrD,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,QAAwB;AAC5C,WAAO,OACJ,YAAY,EACZ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS;AACb,UAAI;AACF,YAAI,KAAK,SAAS,MAAM,GAAG;AACzB,iBAAO;AAAA,QACT;AAEA,cAAM,MAAM,IAAI,IAAI,WAAW,IAAI,EAAE;AACrC,eAAO,IAAI,SAAS,WAAW,MAAM,IAAI,IAAI,WAAW;AAAA,MAC1D,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC,EACA,KAAK,GAAG;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OAAO,QAA6C;AACxD,UAAM,aAAa,KAAK,cAAc,MAAM;AAC5C,UAAM,MAAM,WAAW,KAAK,UAAU,WAAW,mBAAmB,UAAU,CAAC;AAC/E,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAiC;AAAA,MACnE,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAED,QAAI,SAAS,WAAW,OAAO,SAAS,QAAQ,KAAK;AACnD,YAAM,IAAI,kBAAkB,UAAU,MAAM,iCAAiC;AAAA,IAC/E;AAEA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,GAAG,IAAqC;AAC5C,UAAM,WAAW,MAAM,KAAK,QAAQ,MAA6B;AAAA,MAC/D,QAAQ;AAAA,MACR,KAAK,WAAW,KAAK,UAAU,OAAO,mBAAmB,EAAE,CAAC;AAAA,IAC9D,CAAC;AAED,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,OAAO,KAA0C;AACrD,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAiC;AAAA,MACnE,QAAQ;AAAA,MACR,KAAK,WAAW,KAAK,UAAU,WAAW,GAAG;AAAA,IAC/C,CAAC;AAED,WAAO,SAAS;AAAA,EAClB;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chez14/rdap-sdk",
3
- "version": "0.1.1-5",
3
+ "version": "0.1.1-8",
4
4
  "description": "A TypeScript SDK for RDAP.net. Directly calls RDAP APIs from RDAP.net as the main RDAP Server Database.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/client.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { AutonomousSystemResponse, DomainResponse, IpNetworkResponse } from './types';
1
+ import { RdapAutnumResponse, RdapDomainResponse, RdapIpResponse } from './types';
2
2
  import { DefaultFetcher, Fetcher } from './utils/fetcher';
3
+ import { RdapNotFoundError } from './utils/throwables';
3
4
 
4
- export interface RdapOrgClientOptions {
5
+ export interface RdapClientOptions {
5
6
  fetcher?: Fetcher;
6
7
  baseDomain?: string;
7
8
  }
@@ -10,7 +11,7 @@ export class RdapClient {
10
11
  private readonly fetcher: Fetcher;
11
12
  private readonly baseDomain: string;
12
13
 
13
- constructor(options: RdapOrgClientOptions = {}) {
14
+ constructor(options: RdapClientOptions = {}) {
14
15
  this.fetcher = options.fetcher ?? new DefaultFetcher();
15
16
  this.baseDomain = options.baseDomain ?? 'www.rdap.net';
16
17
  }
@@ -43,19 +44,24 @@ export class RdapClient {
43
44
  * @returns Domain information
44
45
  * @example
45
46
  * ```typescript
46
- * const client = new RdapOrgClient();
47
+ * const client = new RdapClient();
47
48
  * const domain = await client.domain('example.com');
48
49
  * // IDN support
49
50
  * const idn = await client.domain('münchen.de');
50
51
  * ```
51
52
  */
52
- async domain(domain: string): Promise<DomainResponse> {
53
+ async domain(domain: string): Promise<RdapDomainResponse> {
53
54
  const punyDomain = this.prepareDomain(domain);
54
- const response = await this.fetcher.fetch<never, DomainResponse>({
55
+ const url = `https://${this.baseDomain}/domain/${encodeURIComponent(punyDomain)}`;
56
+ const response = await this.fetcher.fetch<never, RdapDomainResponse>({
55
57
  method: 'GET',
56
- url: `https://${this.baseDomain}/domain/${encodeURIComponent(punyDomain)}`,
58
+ url,
57
59
  });
58
60
 
61
+ if (response.status === 404 && response.url === url) {
62
+ throw new RdapNotFoundError(`Domain ${domain} has no RDAP server for its TLD`);
63
+ }
64
+
59
65
  return response.data;
60
66
  }
61
67
 
@@ -65,14 +71,14 @@ export class RdapClient {
65
71
  * @returns IP network information
66
72
  * @example
67
73
  * ```typescript
68
- * const client = new RdapOrgClient();
74
+ * const client = new RdapClient();
69
75
  * const ip = await client.ip('8.8.8.8');
70
76
  * // or with CIDR notation
71
77
  * const network = await client.ip('2001:db8::1/128');
72
78
  * ```
73
79
  */
74
- async ip(ip: string): Promise<IpNetworkResponse> {
75
- const response = await this.fetcher.fetch<never, IpNetworkResponse>({
80
+ async ip(ip: string): Promise<RdapIpResponse> {
81
+ const response = await this.fetcher.fetch<never, RdapIpResponse>({
76
82
  method: 'GET',
77
83
  url: `https://${this.baseDomain}/ip/${encodeURIComponent(ip)}`,
78
84
  });
@@ -86,12 +92,12 @@ export class RdapClient {
86
92
  * @returns ASN information
87
93
  * @example
88
94
  * ```typescript
89
- * const client = new RdapOrgClient();
95
+ * const client = new RdapClient();
90
96
  * const asn = await client.autnum(174);
91
97
  * ```
92
98
  */
93
- async autnum(asn: number): Promise<AutonomousSystemResponse> {
94
- const response = await this.fetcher.fetch<never, AutonomousSystemResponse>({
99
+ async autnum(asn: number): Promise<RdapAutnumResponse> {
100
+ const response = await this.fetcher.fetch<never, RdapAutnumResponse>({
95
101
  method: 'GET',
96
102
  url: `https://${this.baseDomain}/autnum/${asn}`,
97
103
  });
package/src/types.ts CHANGED
@@ -1,55 +1,216 @@
1
- /**
2
- * Base response interface for RDAP queries
1
+ /*
2
+ * These files were copied directly from
3
+ * https://github.com/dcoffey-zengenti/node-rdap/blob/aa294812f01730f3ce5f1c384fb92cfbfeaf846f/src/types.ts.
3
4
  */
4
- export interface RdapResponse {
5
- rdapConformance: string[];
6
- notices?: Array<{
7
- title?: string;
8
- description: string[];
9
- links?: Array<{
10
- value: string;
11
- rel: string;
12
- href: string;
13
- type?: string;
14
- }>;
15
- }>;
16
- }
17
-
18
- /**
19
- * Domain response interface
20
- */
21
- export interface DomainResponse extends RdapResponse {
5
+
6
+ export interface RdapLink {
7
+ value: string;
8
+ rel: string;
9
+ href: string;
10
+ hreflang?: string[];
11
+ type?: string;
12
+ media?: string;
13
+ title?: string;
14
+ }
15
+
16
+ export interface RdapEvent {
17
+ eventAction: string;
18
+ eventActor?: string;
19
+ eventDate: string;
20
+ links?: RdapLink[];
21
+ }
22
+
23
+ export interface RdapPublicID {
24
+ type: string;
25
+ identifier: string;
26
+ }
27
+
28
+ export type RdapStatus =
29
+ | 'validated'
30
+ | 'renew prohibited'
31
+ | 'update prohibited'
32
+ | 'transfer prohibited'
33
+ | 'delete prohibited'
34
+ | 'proxy'
35
+ | 'private'
36
+ | 'removed'
37
+ | 'obscured'
38
+ | 'associated'
39
+ | 'active'
40
+ | 'inactive'
41
+ | 'locked'
42
+ | 'pending create'
43
+ | 'pending renew'
44
+ | 'pending transfer'
45
+ | 'pending update'
46
+ | 'pending delete';
47
+
48
+ export type RdapNoticeAndRemarkTypes =
49
+ | 'result set truncated due to authorization'
50
+ | 'result set truncated due to excessive load'
51
+ | 'result set truncated due to unexplainable reasons'
52
+ | 'object truncated due to authorization'
53
+ | 'object truncated due to excessive load'
54
+ | 'object truncated due to unexplainable reasons';
55
+
56
+ export interface RdapRemark {
57
+ title?: string;
58
+ type?: RdapNoticeAndRemarkTypes;
59
+ description: string[];
60
+ links?: RdapLink[];
61
+ }
62
+
63
+ export interface RdapDsData {
64
+ keyTag?: number;
65
+ algorithm?: number;
66
+ digest?: string;
67
+ digestType?: string;
68
+ events?: RdapEvent[];
69
+ links?: RdapLink[];
70
+ }
71
+
72
+ export interface RdapKeyData {
73
+ flags?: number;
74
+ protocol?: number;
75
+ publicKey?: string;
76
+ algorithm?: number;
77
+ events?: RdapEvent[];
78
+ links?: RdapLink[];
79
+ }
80
+
81
+ export interface RdapSecureDNS {
82
+ zoneSigned?: boolean;
83
+ delegationSigned?: boolean;
84
+ maxSigLife?: number;
85
+ dsData?: RdapDsData[];
86
+ keyData?: RdapKeyData[];
87
+ }
88
+
89
+ export type RdapNotice = RdapRemark;
90
+
91
+ export type RdapObjectClass =
92
+ | RdapEntityObjectClass
93
+ | RdapNameserverObjectClass
94
+ | RdapDomainObjectClass;
95
+
96
+ export interface RdapEntityObjectClass {
97
+ objectClassName: 'entity';
98
+ handle?: string;
99
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
+ vcardArray?: any[];
101
+ roles?: string[];
102
+ publicIds?: RdapPublicID[];
103
+ entities?: RdapEntityObjectClass[];
104
+ remarks?: RdapRemark[];
105
+ links?: RdapLink[];
106
+ events?: RdapEvent[];
107
+ asEventActor?: Omit<RdapEvent, 'eventActor'>[];
108
+ status?: RdapStatus[];
109
+ port43?: string;
110
+ networks?: RdapIPNetworkObjectClass[];
111
+ autnums?: RdapAutonomousSystemNumberObjectClass[];
112
+ }
113
+
114
+ export interface RdapNameserverObjectClass {
115
+ objectClassName: 'nameserver';
116
+ handle?: string;
117
+ ldhName?: string;
118
+ unicodeName?: string;
119
+ ipAddresses?: {
120
+ v6: string[];
121
+ v4: string[];
122
+ };
123
+ entities?: RdapEntityObjectClass[];
124
+ status?: RdapStatus[];
125
+ remarks?: RdapRemark[];
126
+ links?: RdapLink[];
127
+ port43?: string;
128
+ events?: RdapEvent[];
129
+ }
130
+
131
+ export interface RdapDomainObjectClass {
22
132
  objectClassName: 'domain';
23
133
  handle?: string;
24
- ldhName: string;
25
- links: Array<{
26
- rel: string;
27
- href: string;
28
- type?: string;
29
- }>;
134
+ ldhName?: string;
135
+ unicodeName?: string;
136
+ variants: {
137
+ relation: string[];
138
+ idnTable: string;
139
+ variantName: {
140
+ ldhName: string;
141
+ unicodeName: string;
142
+ }[];
143
+ }[];
144
+ nameservers: RdapNameserverObjectClass[];
145
+ secureDNS: RdapSecureDNS;
146
+ entities?: RdapEntityObjectClass[];
147
+ status?: RdapStatus[];
148
+ publicIds?: RdapPublicID[];
149
+ remarks: RdapRemark[];
150
+ links?: RdapLink[];
151
+ port43?: string;
152
+ events?: RdapEvent[];
153
+ network?: RdapIPNetworkObjectClass;
30
154
  }
31
155
 
32
- /**
33
- * IP Network response interface
34
- */
35
- export interface IpNetworkResponse extends RdapResponse {
156
+ export interface RdapIPNetworkObjectClass {
36
157
  objectClassName: 'ip network';
37
- handle: string;
38
- startAddress: string;
39
- endAddress: string;
40
- ipVersion: string;
158
+ handle?: string;
159
+ startAddress?: string;
160
+ endAddress?: string;
161
+ ipVersion?: 'v4' | 'v6';
41
162
  name?: string;
42
163
  type?: string;
164
+ country?: string;
165
+ parentHandle?: string;
166
+ status?: RdapStatus[];
167
+ entities?: RdapEntityObjectClass[];
168
+ remarks: RdapRemark[];
169
+ links?: RdapLink[];
170
+ port43?: string;
171
+ events?: RdapEvent[];
43
172
  }
44
173
 
45
- /**
46
- * Autonomous System Number response interface
47
- */
48
- export interface AutonomousSystemResponse extends RdapResponse {
174
+ export interface RdapAutonomousSystemNumberObjectClass {
49
175
  objectClassName: 'autnum';
50
- handle: string;
51
- startAutnum: number;
52
- endAutnum: number;
176
+ handle?: string;
177
+ startAutnum?: string;
178
+ endAutnum?: string;
53
179
  name?: string;
54
180
  type?: string;
181
+ status?: RdapStatus[];
182
+ country?: string;
183
+ entities?: RdapEntityObjectClass[];
184
+ remarks: RdapRemark[];
185
+ links?: RdapLink[];
186
+ port43?: string;
187
+ events?: RdapEvent[];
188
+ }
189
+
190
+ export interface RdapDomainSuccessResponse extends RdapDomainObjectClass {
191
+ rdapConformance: string[];
55
192
  }
193
+
194
+ export interface RdapIpSuccessResponse extends RdapIPNetworkObjectClass {
195
+ rdapConformance: string[];
196
+ }
197
+
198
+ export interface RdapAutnumSuccessResponse extends RdapAutonomousSystemNumberObjectClass {
199
+ rdapConformance: string[];
200
+ }
201
+
202
+ export interface RdapHelpSuccessResponse {
203
+ rdapConformance: string[];
204
+ notices?: RdapNotice[];
205
+ }
206
+
207
+ export interface RdapErrorResponse {
208
+ errorCode: number;
209
+ title?: string;
210
+ description?: string[];
211
+ }
212
+
213
+ export type RdapDomainResponse = RdapErrorResponse & RdapDomainSuccessResponse;
214
+ export type RdapIpResponse = RdapErrorResponse & RdapIpSuccessResponse;
215
+ export type RdapAutnumResponse = RdapErrorResponse & RdapAutnumSuccessResponse;
216
+ export type RdapHelpResponse = RdapErrorResponse & RdapHelpSuccessResponse;
@@ -20,6 +20,7 @@ export interface FetchResponse<T = unknown> {
20
20
  status: number;
21
21
  data: T;
22
22
  headers: Headers;
23
+ url: string;
23
24
  }
24
25
 
25
26
  /**
@@ -70,6 +71,7 @@ export class DefaultFetcher implements Fetcher {
70
71
  status: response.status,
71
72
  data,
72
73
  headers: response.headers,
74
+ url: response.url,
73
75
  };
74
76
  }
75
77
  }
@@ -0,0 +1,6 @@
1
+ export class RdapNotFoundError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'RdapNotFoundError';
5
+ }
6
+ }