Skip to content

Commit 463bb13

Browse files
authored
Merge pull request #3 from cloudnode-pro/api-client
Implement API methods
2 parents 622161c + 9f56a51 commit 463bb13

34 files changed

+3207
-3
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ dist
106106
# Ignore .idea folder
107107
.idea
108108

109-
# Ignore .js and .d.ts files
109+
# Ignore TypeScript build output
110110
*.js
111111
*.d.ts
112+
*.js.map
113+
*.d.ts.map

DOCS.md

Lines changed: 1111 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,68 @@
1-
# hetzner-dns-client
1+
# Node.js Hetzner DNS API Client
2+
3+
[![Hetzner DNS API Version](https://shields.io/badge/v1-%23D50C2D?label=Hetnzner%20DNS%20API&logo=hetzner&labelColor=%2324292E)](https://dns.hetzner.com/api-docs/)
4+
[![Version](https://img.shields.io/npm/v/hetzner-dns-client.svg)](https://npmjs.org/package/hetzner-dns-client)
5+
[![Downloads](https://img.shields.io/npm/dm/hetzner-dns-client.svg)](https://npmjs.org/package/hetzner-dns-client)
6+
27
Hetzner DNS API client for Node.js
8+
9+
## Installation
10+
```bash
11+
npm i hetzner-dns-client
12+
```
13+
14+
## Usage
15+
You can use this client library with your Node.js project.
16+
17+
### JavaScript Example
18+
```js
19+
import {HetznerDnsClient, DnsRecord} from 'hetzner-dns-client';
20+
21+
// create client instance
22+
const client = new HetznerDnsClient("YOUR_API_TOKEN");
23+
// get zone by ID
24+
const zone = await client.zones.get("ZONE_ID");
25+
// create apex/root zone record of type "A" to 127.0.0.1
26+
const record = await zone.createRecord("@", DnsRecord.Type.A, "127.0.0.1");
27+
```
28+
29+
### TypeScript Example
30+
31+
```ts
32+
import {HetznerDnsClient, DnsRecord, Zone} from 'hetzner-dns-client';
33+
34+
// create client instance
35+
const client: HetznerDnsClient = new HetznerDnsClient("YOUR_API_TOKEN");
36+
// get zone by ID
37+
const zone: Zone = await client.zones.get("ZONE_ID");
38+
// create apex/root zone record of type "A" to 127.0.0.1
39+
const record: DnsRecord = await zone.createRecord("@", DnsRecord.Type.A, "127.0.0.1");
40+
```
41+
42+
### Handling Errors
43+
Methods that may throw an error are marked with `throws` in the documentation and specify what error types may be thrown. You can catch these errors with a `try/catch` block.
44+
45+
For example:
46+
47+
```js
48+
try {
49+
const zone = await client.zones.get("ID that does not exist");
50+
}
51+
catch (err) {
52+
if (err instanceof ApiError)
53+
console.error(err); // the Hetzner API returned an error, e.g. "Zone not found"
54+
else if (err instanceof ClientParseError)
55+
console.error(err); // the client could not understand or parse the response from the Hetzner API
56+
else
57+
console.error(err); // some other error occurred
58+
}
59+
```
60+
61+
## API Documentation
62+
The official Hetzner DNS API documentation can be found on [https://dns.hetzner.com/api-docs/](https://dns.hetzner.com/api-docs/).
63+
64+
> **Note**: The Hetzner DNS API documentation appears to be incomplete and contains a few errors. The documentation of this client library is a separate documentation and some functionality may be described differently.
65+
>
66+
> If you find any errors in the documentation, or think that further clarification is needed, please open an issue or pull request.
67+
68+
The client library documentation is available in DOCS.md in this repository.

index.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import HetznerDnsClient from "./lib/HetznerDnsClient.js";
2+
import Zone from "./lib/Zone.js";
3+
import DnsRecord from "./lib/DnsRecord.js";
4+
import PrimaryServer from "./lib/PrimaryServer.js";
5+
import ApiResponse from "./lib/ApiResponse.js";
6+
import Zones from "./lib/Zones.js";
7+
import ClientObject from "./lib/ClientObject.js";
8+
import BulkCreateRecordsPretty from "./lib/BulkCreateRecordsPretty.js";
9+
import BulkUpdateRecordsPretty from "./lib/BulkUpdateRecordsPretty.js";
10+
import ZoneValidationPretty from "./lib/ZoneValidationPretty.js";
11+
import ApiError from "./lib/errors/ApiError.js";
12+
import ClientParseError from "./lib/errors/ClientParseError.js";
13+
import ErrorModel from "./lib/models/ErrorModel";
14+
import ZoneModel from "./lib/models/ZoneModel";
15+
import BulkCreateRecords from "./lib/models/BulkCreateRecords";
16+
import BulkUpdateRecords from "./lib/models/BulkUpdateRecords";
17+
import BaseRecordModel from "./lib/models/BaseRecordModel";
18+
import RecordModel from "./lib/models/RecordModel";
19+
import PrimaryServerModel from "./lib/models/PrimaryServerModel";
20+
import PaginatedZones from "./lib/models/PaginatedZones";
21+
import PaginatedData from "./lib/models/PaginatedData";
22+
import ZoneValidation from "./lib/models/ZoneValidation";
23+
24+
export default HetznerDnsClient;
25+
export {
26+
Zone,
27+
DnsRecord,
28+
PrimaryServer,
29+
ApiResponse,
30+
Zones,
31+
ClientObject,
32+
BulkCreateRecordsPretty,
33+
BulkUpdateRecordsPretty,
34+
ZoneValidationPretty,
35+
ApiError,
36+
ClientParseError,
37+
ErrorModel,
38+
ZoneModel,
39+
BulkCreateRecords,
40+
BulkUpdateRecords,
41+
BaseRecordModel,
42+
RecordModel,
43+
PrimaryServerModel,
44+
PaginatedZones,
45+
PaginatedData,
46+
ZoneValidation
47+
};

lib/ApiResponse.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import HetznerDnsClient from "./HetznerDnsClient.js";
2+
import {Response, RequestInit} from "node-fetch";
3+
import ErrorModel from "./models/ErrorModel.js";
4+
5+
/**
6+
* API response object
7+
* @class
8+
* @template T - Response data model
9+
*/
10+
export default class ApiResponse<T extends ErrorModel> {
11+
12+
/**
13+
* Fetch response
14+
* @type {Response}
15+
* @readonly
16+
*/
17+
public readonly response: Response;
18+
19+
/**
20+
* Raw response body
21+
* @type {ArrayBuffer}
22+
* @readonly
23+
*/
24+
public readonly raw: ArrayBuffer;
25+
26+
/**
27+
* Request options
28+
* @type {RequestInit}
29+
* @readonly
30+
*/
31+
public readonly options: RequestInit;
32+
33+
/**
34+
* API client instance used to make the request
35+
* @type {HetznerDnsClient}
36+
* @readonly
37+
*/
38+
public readonly client: HetznerDnsClient;
39+
40+
/**
41+
* Create a new API response object
42+
* @param {Response} response - Fetch response
43+
* @param {ArrayBuffer} raw - Raw response body
44+
* @param {RequestInit} options - Request options
45+
* @param {HetznerDnsClient} client - API client instance used to make the request
46+
* @internal
47+
*/
48+
public constructor(response: Response, raw: ArrayBuffer, options: RequestInit, client: HetznerDnsClient) {
49+
this.response = response;
50+
this.raw = raw;
51+
this.options = options;
52+
this.client = client;
53+
}
54+
55+
/**
56+
* Get response body as string
57+
* @type {string}
58+
* @readonly
59+
*/
60+
public get body(): string {
61+
return Buffer.from(this.raw).toString();
62+
}
63+
64+
/**
65+
* Get parsed response body (if JSON). `null` if not JSON or parsing fails.
66+
* @type {T | null}
67+
* @readonly
68+
*/
69+
public get json(): T | null {
70+
try {
71+
return JSON.parse(this.body) as T;
72+
}
73+
catch (e) {
74+
return null;
75+
}
76+
}
77+
}

lib/BulkCreateRecordsPretty.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import ClientObject from "./ClientObject.js";
2+
import BulkCreateRecords from "./models/BulkCreateRecords";
3+
import DnsRecord from "./DnsRecord.js";
4+
5+
/**
6+
* Response from bulk creating records
7+
* @class
8+
* @extends {ClientObject<BulkCreateRecords>}
9+
*/
10+
export default class BulkCreateRecordsPretty extends ClientObject<BulkCreateRecords> {
11+
/**
12+
* Invalid records
13+
* @type {BaseRecordModel[]}
14+
* @readonly
15+
*/
16+
public readonly invalidRecords = this._data.invalid_records;
17+
18+
/**
19+
* Records that were created
20+
* @type {Record[]}
21+
* @readonly
22+
*/
23+
public readonly records = this._data.records.map(record => new DnsRecord(this.client, record));
24+
25+
/**
26+
* Valid records
27+
* @type {BaseRecordModel[]}
28+
* @readonly
29+
*/
30+
public readonly validRecords = this._data.valid_records;
31+
}

lib/BulkUpdateRecordsPretty.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import ClientObject from "./ClientObject.js";
2+
import DnsRecord from "./DnsRecord.js";
3+
import BulkUpdateRecords from "./models/BulkUpdateRecords";
4+
5+
/**
6+
* Response from bulk updating records
7+
* @class
8+
* @extends {ClientObject<BulkCreateRecords>}
9+
*/
10+
export default class BulkUpdateRecordsPretty extends ClientObject<BulkUpdateRecords> {
11+
/**
12+
* Failed records
13+
* @type {BaseRecordModel[]}
14+
* @readonly
15+
*/
16+
public readonly failedRecords = this._data.failed_records;
17+
18+
/**
19+
* Records that were updated
20+
* @type {Record[]}
21+
* @readonly
22+
*/
23+
public readonly records = this._data.records.map(record => new DnsRecord(this.client, record));
24+
}

lib/ClientObject.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import HetznerDnsClient from "./HetznerDnsClient.js";
2+
3+
/**
4+
* Client object
5+
* @class
6+
* @template T - Raw data model
7+
*/
8+
export default class ClientObject<T> {
9+
/**
10+
* API client instance
11+
* @type {HetznerDnsClient}
12+
* @readonly
13+
* @private
14+
*/
15+
readonly #client: HetznerDnsClient;
16+
17+
/**
18+
* API client instance
19+
* @type {HetznerDnsClient}
20+
* @readonly
21+
*/
22+
public get client(): HetznerDnsClient {
23+
return this.#client;
24+
}
25+
26+
/**
27+
* Raw data
28+
* @type {T}
29+
* @readonly
30+
* @private
31+
*/
32+
readonly #data: T;
33+
34+
/**
35+
* Raw data
36+
* @type {T}
37+
* @readonly
38+
*/
39+
public get _data(): T {
40+
return this.#data;
41+
}
42+
43+
/**
44+
* Constructor
45+
* @param {HetznerDnsClient} client - API client instance
46+
* @param {T} data - Raw data
47+
* @internal
48+
*/
49+
public constructor(client: HetznerDnsClient, data: T) {
50+
this.#client = client;
51+
this.#data = data;
52+
}
53+
}

0 commit comments

Comments
 (0)