@nictool/dns-resource-record 1.6.1 → 1.8.0
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/CHANGELOG.md +47 -0
- package/README.md +356 -199
- package/dist/dns-rr.cjs +7050 -0
- package/dist/dns-rr.min.js +26 -0
- package/dist/dns-rr.min.js.map +7 -0
- package/index.js +12 -11
- package/lib/binary.js +108 -0
- package/lib/bind.js +96 -0
- package/lib/dns-query.js +67 -0
- package/lib/tinydns.js +128 -44
- package/lib/wire.js +629 -0
- package/package.json +28 -8
- package/rr/TEMPLATE.js +124 -0
- package/rr/a.js +8 -48
- package/rr/aaaa.js +13 -80
- package/rr/apl.js +123 -27
- package/rr/caa.js +27 -50
- package/rr/cert.js +60 -81
- package/rr/cname.js +8 -59
- package/rr/dhcid.js +20 -30
- package/rr/dname.js +10 -32
- package/rr/dnskey.js +38 -32
- package/rr/ds.js +59 -54
- package/rr/hinfo.js +21 -40
- package/rr/hip.js +88 -26
- package/rr/https.js +28 -40
- package/rr/ipseckey.js +97 -18
- package/rr/key.js +39 -29
- package/rr/kx.js +16 -27
- package/rr/loc.js +42 -12
- package/rr/mx.js +17 -48
- package/rr/naptr.js +58 -33
- package/rr/ns.js +8 -36
- package/rr/nsec.js +89 -18
- package/rr/nsec3.js +62 -26
- package/rr/nsec3param.js +56 -53
- package/rr/nxt.js +57 -18
- package/rr/openpgpkey.js +24 -30
- package/rr/ptr.js +7 -47
- package/rr/rp.js +17 -32
- package/rr/rrsig.js +108 -75
- package/rr/sig.js +70 -45
- package/rr/smimea.js +33 -33
- package/rr/soa.js +31 -49
- package/rr/spf.js +15 -18
- package/rr/srv.js +28 -51
- package/rr/sshfp.js +35 -48
- package/rr/svcb.js +27 -40
- package/rr/tlsa.js +34 -34
- package/rr/tsig.js +87 -24
- package/rr/txt.js +77 -68
- package/rr/uri.js +19 -29
- package/rr/wks.js +154 -22
- package/rr.js +290 -109
- package/lib/readme.js +0 -84
package/README.md
CHANGED
|
@@ -1,272 +1,429 @@
|
|
|
1
|
-
[![Module Tests]
|
|
2
|
-
[![Coverage
|
|
1
|
+
[![Module Tests][ci-img]][ci-url]
|
|
2
|
+
[![Test Coverage][cov-img]][cov-url]
|
|
3
3
|
|
|
4
4
|
# dns-resource-record
|
|
5
5
|
|
|
6
|
-
DNS resource record parser, validator, importer, and exporter for node.js & browsers
|
|
6
|
+
DNS resource record parser, validator, importer, and exporter for node.js & browsers
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**Quick Links:** [Getting Started](#getting-started) | [API Reference](#api-reference) | [Browser/CDN](#browser--cdn) | [Supported Records](#supported-records) | [Contributing](#development)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Overview
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- import RRs to and from the following formats:
|
|
12
|
+
This module validates, imports, and exports DNS resource records (RRs) with rigorous RFC compliance and robust test coverage.
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
| :------------------------------------------------------: | :----------------: | :----------------: |
|
|
17
|
-
| **JSON** | :white_check_mark: | :white_check_mark: |
|
|
18
|
-
| **[BIND](https://www.isc.org/bind/) / RFC 1035** | :white_check_mark: | :white_check_mark: |
|
|
19
|
-
| **[Tinydns](https://cr.yp.to/djbdns/tinydns-data.html)** | :white_check_mark: | :white_check_mark: |
|
|
20
|
-
| **MaraDNS** | | :white_check_mark: |
|
|
21
|
-
| **JS** | :white_check_mark: | :white_check_mark: |
|
|
22
|
-
| **PowerDNS** | | |
|
|
23
|
-
| **Wire** | | :white_check_mark: |
|
|
14
|
+
**What you can do:**
|
|
24
15
|
|
|
25
|
-
|
|
16
|
+
- **Validate** DNS records for RFC compliance and well-formedness
|
|
17
|
+
- **Parse/Import** records from BIND zone files, tinydns data files, or JS objects
|
|
18
|
+
- **Export** records to BIND, tinydns, MaraDNS, JSON, or wire format
|
|
19
|
+
- **Manipulate** validated records with type-safe setters
|
|
20
|
+
- **Convert** between formats seamlessly (e.g., tinydns → BIND -> wire)
|
|
26
21
|
|
|
27
|
-
This package
|
|
22
|
+
**Scope:** This package handles individual Resource Records. For zone file operations, see [dns-zone](https://github.com/NicTool/dns-zone).
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
**Quality:** RFC compliance is a first-class concern. If you encounter a valid RR that fails to parse or an invalid RR that passes validation, please [open an issue](https://github.com/NicTool/dns-resource-record/issues).
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
## Supported Records
|
|
27
|
+
|
|
28
|
+
This module supports all current DNS RRs in active use on the internet.
|
|
29
|
+
|
|
30
|
+
| Usage | **Resource Record Types** |
|
|
31
|
+
| :-----------: | :-----------------------------------------------------------: |
|
|
32
|
+
| _Common_ | A, AAAA, CNAME, HTTPS, MX, NS, PTR, SOA, SRV, TXT |
|
|
33
|
+
| _Less Common_ | APL, CERT, DHCID, DNAME, HIP, KX, LOC, NAPTR, SVCB, TSIG, URI |
|
|
34
|
+
| _Security_ | CAA, IPSECKEY, OPENPGPKEY, SMIMEA, SSHFP, TLSA |
|
|
35
|
+
| _DNSSEC_ | DNSKEY, DS, NSEC, NSEC3, NSEC3PARAM, RRSIG |
|
|
36
|
+
| _Obsolete_ | HINFO, KEY, NXT, RP, SIG, SPF, WKS |
|
|
37
|
+
|
|
38
|
+
## Getting Started
|
|
39
|
+
|
|
40
|
+
### Installation
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
npm install @nictool/dns-resource-record
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### ESM and CommonJS
|
|
47
|
+
|
|
48
|
+
The package ships both ESM and CJS, selected automatically via the package `exports` map:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
// ESM
|
|
52
|
+
import * as RR from '@nictool/dns-resource-record'
|
|
53
|
+
import RR, { A, TXT } from '@nictool/dns-resource-record'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
// CommonJS
|
|
58
|
+
const RR = require('@nictool/dns-resource-record')
|
|
59
|
+
const { A, TXT } = require('@nictool/dns-resource-record')
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The default export (the base `RR` class) is reached as `require('@nictool/dns-resource-record').default` from CommonJS.
|
|
63
|
+
|
|
64
|
+
### Validation
|
|
65
|
+
|
|
66
|
+
Validate an A record:
|
|
32
67
|
|
|
33
68
|
```js
|
|
34
69
|
import * as RR from '@nictool/dns-resource-record'
|
|
70
|
+
|
|
71
|
+
const validA = new RR.A({
|
|
72
|
+
owner: 'example.com.',
|
|
73
|
+
address: '192.0.2.1',
|
|
74
|
+
ttl: 3600,
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
console.log(validA.toBind())
|
|
78
|
+
// example.com. 3600 IN A 192.0.2.1
|
|
35
79
|
```
|
|
36
80
|
|
|
37
|
-
|
|
81
|
+
Invalid records throw immediately:
|
|
38
82
|
|
|
39
83
|
```js
|
|
40
|
-
const exampleRRs = {
|
|
41
|
-
A: {
|
|
42
|
-
owner : 'test.example.com.',
|
|
43
|
-
type : 'A',
|
|
44
|
-
address: '192.0.2.127',
|
|
45
|
-
ttl : 3600,
|
|
46
|
-
},
|
|
47
|
-
AAAA: {
|
|
48
|
-
owner : 'test.example.com.',
|
|
49
|
-
type : 'AAAA',
|
|
50
|
-
address: '2605:7900:20:a::4',
|
|
51
|
-
ttl : 3600,
|
|
52
|
-
},
|
|
53
|
-
SOA: {
|
|
54
|
-
owner : 'example.com.',
|
|
55
|
-
type : 'SOA',
|
|
56
|
-
mname : 'matt.example.com.',
|
|
57
|
-
rname : 'ns1.example.com.',
|
|
58
|
-
serial : 1,
|
|
59
|
-
refresh: 7200,
|
|
60
|
-
retry : 3600,
|
|
61
|
-
expire : 1209600,
|
|
62
|
-
minimum: 3600,
|
|
63
|
-
ttl : 3600,
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
84
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'ttl' => 3600,
|
|
71
|
-
'class' => 'IN',
|
|
72
|
-
'type' => 'SOA',
|
|
73
|
-
'mname' => 'matt.example.com.',
|
|
74
|
-
'rname' => 'ns1.example.com.',
|
|
75
|
-
'serial' => 1,
|
|
76
|
-
'refresh' => 7200,
|
|
77
|
-
'retry' => 3600,
|
|
78
|
-
'expire' => 1209600,
|
|
79
|
-
'minimum' => 3600
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
console.error(e.message) // invalid RRs throw
|
|
85
|
+
new RR.A({ owner: 'example.com.', address: 'not-an-ip', ttl: 3600 })
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error(err.message) // Error: A address must be IPv4
|
|
84
88
|
}
|
|
85
89
|
```
|
|
86
90
|
|
|
87
|
-
|
|
91
|
+
This library enforces RFC-compliance during construction, catching errors early.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## API Reference
|
|
96
|
+
|
|
97
|
+
### Understanding Record Structure
|
|
98
|
+
|
|
99
|
+
Every DNS record has these standard fields:
|
|
100
|
+
|
|
101
|
+
- **owner** — The domain name this record belongs to (always fully qualified, e.g., `example.com.`)
|
|
102
|
+
- **type** — The record type (A, AAAA, MX, TXT, etc.)
|
|
103
|
+
- **ttl** — Time to live in seconds
|
|
104
|
+
- **class** — Almost always `IN` (Internet); omitted in examples
|
|
105
|
+
|
|
106
|
+
Plus **rdata fields** specific to each record type (e.g., `address` for A records, `preference`/`exchange` for MX records).
|
|
107
|
+
|
|
108
|
+
### Core Workflows
|
|
109
|
+
|
|
110
|
+
#### 1. **Validate & Create** — Use the Constructor
|
|
111
|
+
|
|
112
|
+
When you have data in JavaScript object form:
|
|
88
113
|
|
|
89
114
|
```js
|
|
90
|
-
|
|
115
|
+
new RR.SOA({
|
|
116
|
+
owner: 'example.com.',
|
|
117
|
+
mname: 'ns1.example.com.',
|
|
118
|
+
rname: 'hostmaster.example.com.',
|
|
119
|
+
serial: 2024042201,
|
|
120
|
+
refresh: 7200,
|
|
121
|
+
retry: 3600,
|
|
122
|
+
expire: 1209600,
|
|
123
|
+
minimum: 3600,
|
|
124
|
+
ttl: 3600,
|
|
125
|
+
})
|
|
91
126
|
```
|
|
92
127
|
|
|
93
|
-
|
|
128
|
+
**When to use:** Building records programmatically, validating user input, working with API responses.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
#### 2. **Parse BIND Format** — Use `fromBind()`
|
|
133
|
+
|
|
134
|
+
When you have a line from a BIND zone file:
|
|
94
135
|
|
|
95
136
|
```js
|
|
96
|
-
|
|
97
|
-
|
|
137
|
+
const rr = RR.A.fromBind('www.example.com. 3600 IN A 192.0.2.1\n')
|
|
138
|
+
console.log(rr.get('address')) // '192.0.2.1'
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**When to use:** Processing BIND zone files, DNS configs, or standard zone file exports.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
#### 3. **Parse Tinydns Format** — Use `fromTinydns()`
|
|
146
|
+
|
|
147
|
+
When you have a line from a tinydns data file:
|
|
98
148
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
149
|
+
```js
|
|
150
|
+
const rr = RR.A.fromTinydns('+www.example.com:192.0.2.1:3600::\n')
|
|
151
|
+
console.log(rr.get('address')) // '192.0.2.1'
|
|
102
152
|
```
|
|
103
153
|
|
|
104
|
-
|
|
154
|
+
**When to use:** Working with djbdns/tinydns configurations, or when parsing tinydns data files.
|
|
155
|
+
|
|
156
|
+
---
|
|
105
157
|
|
|
106
|
-
|
|
158
|
+
#### 4. **Export to BIND** — Use `toBind()`
|
|
107
159
|
|
|
108
|
-
|
|
160
|
+
Convert any validated record to BIND zone file format:
|
|
109
161
|
|
|
110
162
|
```js
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class: 'IN',
|
|
163
|
+
new RR.MX({
|
|
164
|
+
owner: 'example.com.',
|
|
165
|
+
preference: 10,
|
|
166
|
+
exchange: 'mail.example.com.',
|
|
116
167
|
ttl: 3600,
|
|
117
|
-
|
|
118
|
-
|
|
168
|
+
}).toBind()
|
|
169
|
+
// example.com. 3600 IN MX 10 mail.example.com.
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**When to use:** Generating zone files, displaying records for editing, exporting to BIND nameservers.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
#### 5. **Export to Tinydns** — Use `toTinydns()`
|
|
177
|
+
|
|
178
|
+
Convert to tinydns data file format:
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
new RR.A({
|
|
182
|
+
owner: 'example.com.',
|
|
183
|
+
address: '192.0.2.1',
|
|
184
|
+
ttl: 3600,
|
|
185
|
+
}).toTinydns()
|
|
186
|
+
// +example.com:192.0.2.1:3600::
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**When to use:** Generating tinydns data files, migrating to djbdns, or integrating with tinydns tooling.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
#### 6. **Round-Trip Conversion**
|
|
194
|
+
|
|
195
|
+
Parse from one format, export to another:
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
// tinydns → BIND
|
|
199
|
+
const fromTiny = RR.CAA.fromTinydns(
|
|
200
|
+
':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n',
|
|
201
|
+
)
|
|
202
|
+
console.log(fromTiny.toBind())
|
|
203
|
+
// ns1.example.com. 3600 IN CAA 0 issue "http://letsencrypt.org"
|
|
119
204
|
```
|
|
120
205
|
|
|
121
|
-
|
|
206
|
+
**When to use:** DNS migrations, format conversions, tool interoperability.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### Manipulating Records
|
|
122
211
|
|
|
123
|
-
|
|
212
|
+
Use **setter methods** to modify validated records. Setter names follow the pattern `set` + `FieldName` (camelCased):
|
|
124
213
|
|
|
125
214
|
```js
|
|
126
|
-
|
|
127
|
-
|
|
215
|
+
const a = new RR.A({
|
|
216
|
+
owner: 'example.com.',
|
|
217
|
+
address: '192.0.2.1',
|
|
218
|
+
ttl: 3600,
|
|
219
|
+
})
|
|
128
220
|
|
|
129
|
-
|
|
221
|
+
a.setAddress('192.0.2.2')
|
|
222
|
+
a.setTtl(7200)
|
|
130
223
|
|
|
131
|
-
|
|
132
|
-
//
|
|
224
|
+
console.log(a.toBind())
|
|
225
|
+
// example.com. 7200 IN A 192.0.2.2
|
|
133
226
|
```
|
|
134
227
|
|
|
135
|
-
|
|
228
|
+
Setters include validation. Invalid values throw with helpful error messages.
|
|
136
229
|
|
|
137
|
-
|
|
230
|
+
For a list of available setters, check `getFields('rdata')` for your record type:
|
|
138
231
|
|
|
139
232
|
```js
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
233
|
+
new RR.SSHFP(null).getFields('rdata')
|
|
234
|
+
// ['algorithm', 'fptype', 'fingerprint']
|
|
235
|
+
// So use: setAlgorithm(), setFptype(), setFingerprint()
|
|
143
236
|
```
|
|
144
237
|
|
|
145
|
-
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### Metadata Methods
|
|
241
|
+
|
|
242
|
+
Get information about record types:
|
|
243
|
+
|
|
244
|
+
#### `getFields([section])`
|
|
146
245
|
|
|
147
|
-
|
|
246
|
+
Get field names for a record type. Pass `'rdata'` to get only the custom fields:
|
|
148
247
|
|
|
149
248
|
```js
|
|
150
|
-
|
|
151
|
-
|
|
249
|
+
new RR.A(null).getFields() // ['owner', 'ttl', 'class', 'type', 'address']
|
|
250
|
+
new RR.A(null).getFields('rdata') // ['address']
|
|
251
|
+
new RR.MX(null).getFields('rdata') // ['preference', 'exchange']
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### `getRFCs()`
|
|
255
|
+
|
|
256
|
+
Get RFC references for a record type:
|
|
152
257
|
|
|
153
|
-
|
|
154
|
-
|
|
258
|
+
```js
|
|
259
|
+
new RR.A(null).getRFCs() // [1035]
|
|
260
|
+
new RR.MX(null).getRFCs() // [1035, 2181, 7505]
|
|
261
|
+
new RR.SRV(null).getRFCs() // [2782]
|
|
155
262
|
```
|
|
156
263
|
|
|
157
|
-
|
|
264
|
+
#### `getCanonical()`
|
|
158
265
|
|
|
159
|
-
|
|
266
|
+
Get a record with all fields populated with default/canonical values:
|
|
160
267
|
|
|
161
268
|
```js
|
|
162
|
-
|
|
269
|
+
new RR.AAAA(null).getCanonical()
|
|
270
|
+
// {
|
|
271
|
+
// owner: 'host.example.com.',
|
|
272
|
+
// address: '2001:0db8:0020:000a:0000:0000:0000:0004',
|
|
273
|
+
// class: 'IN',
|
|
274
|
+
// ttl: 3600,
|
|
275
|
+
// type: 'AAAA'
|
|
276
|
+
// }
|
|
163
277
|
```
|
|
164
278
|
|
|
165
|
-
|
|
279
|
+
#### `toJSON()` / `JSON.stringify()`
|
|
166
280
|
|
|
167
|
-
|
|
281
|
+
Serialize a record to a plain object:
|
|
168
282
|
|
|
169
283
|
```js
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
'ttl' => 3600,
|
|
174
|
-
'class' => 'IN',
|
|
175
|
-
'type' => 'A',
|
|
176
|
-
'address' => 'oops'
|
|
177
|
-
}
|
|
284
|
+
const a = new RR.A({ owner: 'example.com.', address: '192.0.2.1', ttl: 3600 })
|
|
285
|
+
JSON.stringify(a)
|
|
286
|
+
// {"owner":"example.com.","ttl":3600,"class":"IN","type":"A","address":"192.0.2.1"}
|
|
178
287
|
```
|
|
179
288
|
|
|
180
|
-
|
|
289
|
+
---
|
|
181
290
|
|
|
182
|
-
###
|
|
291
|
+
### Advanced: Bypassing Validation
|
|
183
292
|
|
|
184
|
-
|
|
293
|
+
The `set()` method bypasses validation (use carefully):
|
|
185
294
|
|
|
186
295
|
```js
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}).toBind())
|
|
190
|
-
ns1.example.com 3600 IN CAA 0 issue "http://letsencrypt.org"
|
|
296
|
+
record.set('address', 'invalid-value')
|
|
297
|
+
// Works, but now the record is malformed — useful only for testing or low-level manipulation
|
|
191
298
|
```
|
|
192
299
|
|
|
193
|
-
|
|
300
|
+
**Note:** Validation is there to protect data integrity. Use at your own risk.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Browser & CDN
|
|
305
|
+
|
|
306
|
+
Use this module directly in browsers via CDN:
|
|
307
|
+
|
|
308
|
+
```html
|
|
309
|
+
<!DOCTYPE html>
|
|
310
|
+
<html>
|
|
311
|
+
<head>
|
|
312
|
+
<title>DNS Record Validator</title>
|
|
313
|
+
</head>
|
|
314
|
+
<body>
|
|
315
|
+
<h1>DNS Record Validator</h1>
|
|
316
|
+
<pre id="output"></pre>
|
|
317
|
+
|
|
318
|
+
<script type="module">
|
|
319
|
+
// Import from unpkg (or jsdelivr, esm.sh)
|
|
320
|
+
import * as RR from 'https://unpkg.com/@nictool/dns-resource-record@latest/dist/dns-rr.min.js'
|
|
321
|
+
|
|
322
|
+
// Use just like Node.js
|
|
323
|
+
const record = new RR.A({
|
|
324
|
+
owner: 'example.com.',
|
|
325
|
+
address: '192.0.2.1',
|
|
326
|
+
ttl: 3600,
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
document.getElementById('output').textContent = record.toBind()
|
|
330
|
+
</script>
|
|
331
|
+
</body>
|
|
332
|
+
</html>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Available CDNs:**
|
|
336
|
+
|
|
337
|
+
- **unpkg:** `https://unpkg.com/@nictool/dns-resource-record/dist/dns-rr.min.js`
|
|
338
|
+
- **jsdelivr:** `https://cdn.jsdelivr.net/npm/@nictool/dns-resource-record/dist/dns-rr.min.js`
|
|
339
|
+
- **esm.sh:** `https://esm.sh/@nictool/dns-resource-record`
|
|
340
|
+
|
|
341
|
+
**Live example:** See [nictool.github.io/builder/](https://nictool.github.io/builder/) for an interactive DNS record editor using this library.
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Important Concepts
|
|
346
|
+
|
|
347
|
+
### Domain Name Normalization
|
|
348
|
+
|
|
349
|
+
Domain owner names are:
|
|
350
|
+
|
|
351
|
+
- **Stored fully qualified** (absolute), e.g., `example.com.` not `example.com`
|
|
352
|
+
- **Normalized to lowercase** because:
|
|
353
|
+
- DNS is case-insensitive (RFC 4343, RFC 1035)
|
|
354
|
+
- This library enforces automatic duplicate suppression
|
|
355
|
+
- DNSSEC canonicalization requires it (RFC 4034)
|
|
356
|
+
- Wire format for most RRs requires lowercase
|
|
357
|
+
|
|
358
|
+
**Example:**
|
|
359
|
+
|
|
360
|
+
```js
|
|
361
|
+
const r = new RR.A({ owner: 'EXAMPLE.COM.', address: '192.0.2.1', ttl: 3600 })
|
|
362
|
+
r.get('owner') // 'example.com.' — uppercase normalized to lowercase
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Owner names are required to be fully qualified (trailing dot). Unqualified
|
|
366
|
+
names throw at construction; this library does not add the dot for you.
|
|
367
|
+
|
|
368
|
+
### Relative vs Absolute Names
|
|
369
|
+
|
|
370
|
+
Master zone file expansions (relative domain names) are handled by [dns-zone](https://github.com/NicTool/dns-zone). This library works only with fully qualified names.
|
|
371
|
+
|
|
372
|
+
### Export Options
|
|
373
|
+
|
|
374
|
+
The `toBind()` method accepts a zone-options object (typically supplied by
|
|
375
|
+
[dns-zone](https://github.com/NicTool/dns-zone) when emitting full zone files)
|
|
376
|
+
to elide redundant per-record output:
|
|
377
|
+
|
|
378
|
+
```js
|
|
379
|
+
record.toBind({
|
|
380
|
+
origin: 'example.com.', // strips matching suffix from owner; emits '@' for an exact match
|
|
381
|
+
ttl: 3600, // the zone default; lets `hide.ttl` skip records whose TTL matches it
|
|
382
|
+
previousOwner: 'example.com.', // lets `hide.sameOwner` blank the owner column when it repeats
|
|
383
|
+
hide: {
|
|
384
|
+
ttl: true, // omit TTL when it equals the zone default
|
|
385
|
+
class: true, // omit class column (usually IN)
|
|
386
|
+
sameOwner: true, // omit owner when it matches `previousOwner`
|
|
387
|
+
origin: true, // shorten owners relative to `origin`
|
|
388
|
+
},
|
|
389
|
+
})
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
See [dns-zone](https://github.com/NicTool/dns-zone) for the full per-zone pipeline that supplies these options.
|
|
393
|
+
|
|
394
|
+
## Development
|
|
395
|
+
|
|
396
|
+
No external dependencies. Runs on node.js and modern browsers.
|
|
397
|
+
|
|
398
|
+
**Key scripts:**
|
|
399
|
+
|
|
400
|
+
- `npm test` — Run all tests with node's built-in test runner
|
|
401
|
+
- `npm run watch` — Run tests in watch mode during development
|
|
402
|
+
- `npm run lint` — Check code with ESLint
|
|
403
|
+
- `npm run format` — Auto-format with Prettier and fix linting issues
|
|
404
|
+
- `npm run build` — Regenerate the browser and CommonJS bundles in `dist/`
|
|
405
|
+
- `npm run test:coverage` — Generate test coverage report
|
|
406
|
+
|
|
407
|
+
**Architecture:**
|
|
408
|
+
|
|
409
|
+
- **rr.js** — Base class with shared DNS logic and validation
|
|
410
|
+
- **rr/\*.js** — Individual RR type implementations
|
|
411
|
+
- **test/\*.js** — Comprehensive test suite for each RR type
|
|
412
|
+
|
|
413
|
+
## References
|
|
414
|
+
|
|
415
|
+
- [DNS Record Types (Wikipedia)](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
|
|
416
|
+
- [DNS Terminology (NicTool Dictionary)](https://nictool.github.io/Dictionary)
|
|
417
|
+
- [dns-zone](https://www.npmjs.com/package/@nictool/dns-zone) — Zone file operations
|
|
418
|
+
- [dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver) — Nameserver management
|
|
419
|
+
|
|
420
|
+
---
|
|
194
421
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
| **AAAA** | :white_check_mark: | :white_check_mark: |
|
|
204
|
-
| **CNAME** | :white_check_mark: | :white_check_mark: |
|
|
205
|
-
| **HTTPS** | :white_check_mark: | :white_check_mark: |
|
|
206
|
-
| **MX** | :white_check_mark: | :white_check_mark: |
|
|
207
|
-
| **NS** | :white_check_mark: | :white_check_mark: |
|
|
208
|
-
| **PTR** | :white_check_mark: | :white_check_mark: |
|
|
209
|
-
| **SRV** | :white_check_mark: | :white_check_mark: |
|
|
210
|
-
| **TXT** | :white_check_mark: | :white_check_mark: |
|
|
211
|
-
| _Less Common_ |
|
|
212
|
-
| **APL** | :white_check_mark: | :white_check_mark: |
|
|
213
|
-
| **CERT** | :white_check_mark: | :white_check_mark: |
|
|
214
|
-
| **DHCID** | :white_check_mark: | :white_check_mark: |
|
|
215
|
-
| **DNAME** | :white_check_mark: | :white_check_mark: |
|
|
216
|
-
| **HIP** | :white_check_mark: | :white_check_mark: |
|
|
217
|
-
| **KEY** | :white_check_mark: | :white_check_mark: |
|
|
218
|
-
| **KX** | :white_check_mark: | :white_check_mark: |
|
|
219
|
-
| **LOC** | :white_check_mark: | :white_check_mark: |
|
|
220
|
-
| **NAPTR** | :white_check_mark: | :white_check_mark: |
|
|
221
|
-
| **SOA** | :white_check_mark: | :white_check_mark: |
|
|
222
|
-
| **SVCB** | :white_check_mark: | :white_check_mark: |
|
|
223
|
-
| **TSIG** | :white_check_mark: | :white_check_mark: |
|
|
224
|
-
| **URI** | :white_check_mark: | :white_check_mark: |
|
|
225
|
-
| _Security_ |
|
|
226
|
-
| **CAA** | :white_check_mark: | :white_check_mark: |
|
|
227
|
-
| **IPSECKEY** | :white_check_mark: | :white_check_mark: |
|
|
228
|
-
| **OPENPGPKEY** | :white_check_mark: | :white_check_mark: |
|
|
229
|
-
| **SMIMEA** | :white_check_mark: | :white_check_mark: |
|
|
230
|
-
| **SSHFP** | :white_check_mark: | :white_check_mark: |
|
|
231
|
-
| **TLSA** | :white_check_mark: | :white_check_mark: |
|
|
232
|
-
| _DNSSEC_ |
|
|
233
|
-
| **DNSKEY** | :white_check_mark: | :white_check_mark: |
|
|
234
|
-
| **DS** | :white_check_mark: | :white_check_mark: |
|
|
235
|
-
| **NSEC** | :white_check_mark: | :white_check_mark: |
|
|
236
|
-
| **NSEC3** | :white_check_mark: | :white_check_mark: |
|
|
237
|
-
| **NSEC3PARAM** | :white_check_mark: | :white_check_mark: |
|
|
238
|
-
| **RRSIG** | :white_check_mark: | :white_check_mark: |
|
|
239
|
-
| _Deprecated_ |
|
|
240
|
-
| **NXT** | :white_check_mark: | :white_check_mark: |
|
|
241
|
-
| **SPF** | :white_check_mark: | :white_check_mark: |
|
|
242
|
-
| _Obsolete_ |
|
|
243
|
-
| **HINFO** | :white_check_mark: | :white_check_mark: |
|
|
244
|
-
| **RP** | :white_check_mark: | :white_check_mark: |
|
|
245
|
-
| **SIG** | :white_check_mark: | :white_check_mark: |
|
|
246
|
-
| **WKS** | :white_check_mark: | :white_check_mark: |
|
|
247
|
-
|
|
248
|
-
## TIPS
|
|
249
|
-
|
|
250
|
-
- Domain owner names are:
|
|
251
|
-
- stored fully qualified, aka absolute.
|
|
252
|
-
- normalized to lower case, because:
|
|
253
|
-
- DNS is case insensitive (see RFCs 4343, 1035, 1034)
|
|
254
|
-
- this library enforces duplicate suppression
|
|
255
|
-
- DNSSEC canonicalization (see RFC 4034)
|
|
256
|
-
- wire format for most RRs require it
|
|
257
|
-
- Master Zone File expansions exist in [dns-zone](https://github.com/NicTool/dns-zone)
|
|
258
|
-
- to{Bind|MaraDNS} output can be influenced (suppress TTL, class, relative domain names) with an options object. See it in `bin/dns-zone` in the [dns-zone](https://github.com/NicTool/dns-zone) package.
|
|
259
|
-
|
|
260
|
-
## SEE ALSO
|
|
261
|
-
|
|
262
|
-
- [Dictionary of DNS terms](https://nictool.github.io/web/Dictionary)
|
|
263
|
-
- [Wikipedia, List of DNS Record Types](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
|
|
264
|
-
- @nictool/[dns-zone](https://www.npmjs.com/package/@nictool/dns-zone)
|
|
265
|
-
- @nictool/[dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver)
|
|
266
|
-
|
|
267
|
-
## DEVELOP
|
|
268
|
-
|
|
269
|
-
- There are no dependencies. That's no accident.
|
|
270
|
-
- ESM browsers and node.js
|
|
271
|
-
- Platform independence is a goal
|
|
272
|
-
- [x] CI tests are on linux, windows, and macOS
|
|
422
|
+
[ci-img]: https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml/badge.svg
|
|
423
|
+
[ci-url]: https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml
|
|
424
|
+
[cov-img]: https://coveralls.io/repos/github/NicTool/dns-resource-record/badge.svg
|
|
425
|
+
[cov-url]: https://coveralls.io/github/NicTool/dns-resource-record
|
|
426
|
+
[bind-url]: https://www.isc.org/bind/
|
|
427
|
+
[knot-url]: https://www.knot-dns.cz
|
|
428
|
+
[nsd-url]: https://www.nlnetlabs.nl/projects/nsd/about/
|
|
429
|
+
[pdns-url]: https://www.powerdns.com/powerdns-authoritative-server
|