@nictool/dns-resource-record 1.6.0 → 1.7.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 +45 -6
- package/README.md +328 -198
- 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 +94 -0
- package/lib/dns-query.js +67 -0
- package/lib/tinydns.js +128 -44
- package/lib/wire.js +519 -0
- package/package.json +29 -10
- 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 +58 -87
- package/rr/cname.js +7 -63
- package/rr/dhcid.js +20 -30
- package/rr/dname.js +9 -36
- package/rr/dnskey.js +38 -32
- package/rr/ds.js +43 -57
- 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 +16 -51
- 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 +80 -85
- package/rr/sig.js +70 -45
- package/rr/smimea.js +33 -33
- package/rr/soa.js +31 -49
- package/rr/spf.js +10 -17
- package/rr/srv.js +22 -62
- package/rr/sshfp.js +25 -53
- package/rr/svcb.js +27 -40
- package/rr/tlsa.js +34 -34
- package/rr/tsig.js +87 -24
- package/rr/txt.js +40 -59
- package/rr/uri.js +19 -29
- package/rr/wks.js +154 -22
- package/rr.js +290 -109
- package/lib/readme.js +0 -84
package/CHANGELOG.md
CHANGED
|
@@ -4,17 +4,54 @@ Notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
#### Unreleased
|
|
6
6
|
|
|
7
|
-
### [1.
|
|
7
|
+
### [1.7.0] - 2026-04-20
|
|
8
8
|
|
|
9
|
-
####
|
|
9
|
+
#### Fixes
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
11
|
+
- rr/txt: chunk by UTF-8 bytes (vs ASCII)
|
|
12
|
+
- rr/rrsig: validate "type covered" correctly
|
|
13
|
+
|
|
14
|
+
#### Changes
|
|
15
|
+
|
|
16
|
+
- RR is strictly a factory now
|
|
17
|
+
- no longer returns a different object based on bindLine or tinyLine
|
|
18
|
+
- doc(CAA, DS): added RFC 9619
|
|
19
|
+
- openpgpkey: reject keys with non-ASCII
|
|
20
|
+
- tinydns: name any out-of-range chars in error msg
|
|
21
|
+
- fromBind: use a tokenizing parser (vs regexes)
|
|
22
|
+
|
|
23
|
+
#### Additions
|
|
24
|
+
|
|
25
|
+
- add rr/TEMPLATE.js with lots of docs
|
|
26
|
+
- declarative rdataFields to remove lots of boilerplate from rr/all
|
|
27
|
+
- browser compat enhancements
|
|
28
|
+
- rollup dns-rr.min.js + min.js.map
|
|
29
|
+
- add `static typeName` as constructor.name doesn't survive minification
|
|
30
|
+
- feat(lib/binary): add shared binary functions
|
|
31
|
+
- change: replace `Buffer` with Uint8Array, DataView, and math
|
|
32
|
+
- feat(lib/wire): add wire format helpers
|
|
33
|
+
- feat(fromWire): added wire format parsers
|
|
34
|
+
- used to round-trip DNS and validate parsing & formatting
|
|
35
|
+
- feat(fromBind): use a parser (vs regexes)
|
|
36
|
+
- test: add dnsLiveTests, test `toWire()` against live NSD & tinydns
|
|
37
|
+
- uncovered edge cases in round trips between formats
|
|
38
|
+
|
|
39
|
+
### [1.6.1] - 2026-04-20
|
|
40
|
+
|
|
41
|
+
- doc(README): add wire export format
|
|
42
|
+
- ci: split coverage to new GHA file, trigger on push to main
|
|
43
|
+
|
|
44
|
+
### [1.6.0] - 2026-03-26
|
|
45
|
+
|
|
46
|
+
- feat(toWire): add wire export format to every RR, fixes #23
|
|
47
|
+
- feat(getTags): added to all RR types
|
|
14
48
|
- values: common, obsolete, security, dnssec
|
|
15
|
-
-
|
|
49
|
+
- feat(getCanonical): added to RRs where missing
|
|
16
50
|
- added RFCs to: AAAA 5952, NAPTR 4848, SIG 3755, TLSA 7671
|
|
17
51
|
- TXT: 4408, 6376, 7208
|
|
52
|
+
- doc(README): categorize RR types.
|
|
53
|
+
- doc(README): generate the supported RRs table
|
|
54
|
+
- test: add tests for toWire, getCanonical, getTags
|
|
18
55
|
|
|
19
56
|
### [1.5.0] - 2026-03-22
|
|
20
57
|
|
|
@@ -379,3 +416,5 @@ Notable changes to this project are documented in this file.
|
|
|
379
416
|
[1.4.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.4.0
|
|
380
417
|
[1.5.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.5.0
|
|
381
418
|
[1.6.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.6.0
|
|
419
|
+
[1.6.1]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.6.1
|
|
420
|
+
[1.7.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.7.0
|
package/README.md
CHANGED
|
@@ -1,266 +1,396 @@
|
|
|
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/)** | :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** | | |
|
|
14
|
+
**What you can do:**
|
|
23
15
|
|
|
24
|
-
|
|
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)
|
|
25
21
|
|
|
26
|
-
This package
|
|
22
|
+
**Scope:** This package handles individual Resource Records. For zone file operations, see [dns-zone](https://github.com/NicTool/dns-zone).
|
|
27
23
|
|
|
28
|
-
|
|
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).
|
|
29
25
|
|
|
30
|
-
|
|
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
|
+
### Validation
|
|
47
|
+
|
|
48
|
+
Validate an A record:
|
|
31
49
|
|
|
32
50
|
```js
|
|
33
51
|
import * as RR from '@nictool/dns-resource-record'
|
|
52
|
+
|
|
53
|
+
const validA = new RR.A({
|
|
54
|
+
owner: 'example.com.',
|
|
55
|
+
address: '192.0.2.1',
|
|
56
|
+
ttl: 3600,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
console.log(validA.toBind())
|
|
60
|
+
// example.com 3600 IN A 192.0.2.1
|
|
34
61
|
```
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
Invalid records throw immediately:
|
|
37
64
|
|
|
38
65
|
```js
|
|
39
|
-
const exampleRRs = {
|
|
40
|
-
A: {
|
|
41
|
-
owner : 'test.example.com.',
|
|
42
|
-
type : 'A',
|
|
43
|
-
address: '192.0.2.127',
|
|
44
|
-
ttl : 3600,
|
|
45
|
-
},
|
|
46
|
-
AAAA: {
|
|
47
|
-
owner : 'test.example.com.',
|
|
48
|
-
type : 'AAAA',
|
|
49
|
-
address: '2605:7900:20:a::4',
|
|
50
|
-
ttl : 3600,
|
|
51
|
-
},
|
|
52
|
-
SOA: {
|
|
53
|
-
owner : 'example.com.',
|
|
54
|
-
type : 'SOA',
|
|
55
|
-
mname : 'matt.example.com.',
|
|
56
|
-
rname : 'ns1.example.com.',
|
|
57
|
-
serial : 1,
|
|
58
|
-
refresh: 7200,
|
|
59
|
-
retry : 3600,
|
|
60
|
-
expire : 1209600,
|
|
61
|
-
minimum: 3600,
|
|
62
|
-
ttl : 3600,
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
66
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
'ttl' => 3600,
|
|
70
|
-
'class' => 'IN',
|
|
71
|
-
'type' => 'SOA',
|
|
72
|
-
'mname' => 'matt.example.com.',
|
|
73
|
-
'rname' => 'ns1.example.com.',
|
|
74
|
-
'serial' => 1,
|
|
75
|
-
'refresh' => 7200,
|
|
76
|
-
'retry' => 3600,
|
|
77
|
-
'expire' => 1209600,
|
|
78
|
-
'minimum' => 3600
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
console.error(e.message) // invalid RRs throw
|
|
67
|
+
new RR.A({ owner: 'example.com.', address: 'not-an-ip' })
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(err.message) // Error: A address must be IPv4
|
|
83
70
|
}
|
|
84
71
|
```
|
|
85
72
|
|
|
86
|
-
|
|
73
|
+
This library enforces RFC-compliance during construction, catching errors early.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## API Reference
|
|
78
|
+
|
|
79
|
+
### Understanding Record Structure
|
|
80
|
+
|
|
81
|
+
Every DNS record has these standard fields:
|
|
82
|
+
|
|
83
|
+
- **owner** — The domain name this record belongs to (always fully qualified, e.g., `example.com.`)
|
|
84
|
+
- **type** — The record type (A, AAAA, MX, TXT, etc.)
|
|
85
|
+
- **ttl** — Time to live in seconds
|
|
86
|
+
- **class** — Almost always `IN` (Internet); omitted in examples
|
|
87
|
+
|
|
88
|
+
Plus **rdata fields** specific to each record type (e.g., `address` for A records, `preference`/`exchange` for MX records).
|
|
89
|
+
|
|
90
|
+
### Core Workflows
|
|
91
|
+
|
|
92
|
+
#### 1. **Validate & Create** — Use the Constructor
|
|
93
|
+
|
|
94
|
+
When you have data in JavaScript object form:
|
|
87
95
|
|
|
88
96
|
```js
|
|
89
|
-
|
|
97
|
+
new RR.SOA({
|
|
98
|
+
owner: 'example.com.',
|
|
99
|
+
mname: 'ns1.example.com.',
|
|
100
|
+
rname: 'hostmaster.example.com.',
|
|
101
|
+
serial: 2024042201,
|
|
102
|
+
refresh: 7200,
|
|
103
|
+
retry: 3600,
|
|
104
|
+
expire: 1209600,
|
|
105
|
+
minimum: 3600,
|
|
106
|
+
ttl: 3600,
|
|
107
|
+
})
|
|
90
108
|
```
|
|
91
109
|
|
|
92
|
-
|
|
110
|
+
**When to use:** Building records programmatically, validating user input, working with API responses.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
#### 2. **Parse BIND Format** — Use `fromBind()`
|
|
115
|
+
|
|
116
|
+
When you have a line from a BIND zone file:
|
|
93
117
|
|
|
94
118
|
```js
|
|
95
|
-
|
|
96
|
-
|
|
119
|
+
const rr = RR.A.fromBind('www.example.com. 3600 IN A 192.0.2.1\n')
|
|
120
|
+
console.log(rr.get('address')) // '192.0.2.1'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**When to use:** Processing BIND zone files, DNS configs, or standard zone file exports.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
#### 3. **Parse Tinydns Format** — Use `fromTinydns()`
|
|
128
|
+
|
|
129
|
+
When you have a line from a tinydns data file:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
const rr = RR.A.fromTinydns('+www.example.com:192.0.2.1:3600::\n')
|
|
133
|
+
console.log(rr.get('address')) // '192.0.2.1'
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**When to use:** Working with djbdns/tinydns configurations, or when parsing tinydns data files.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
#### 4. **Export to BIND** — Use `toBind()`
|
|
141
|
+
|
|
142
|
+
Convert any validated record to BIND zone file format:
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
new RR.MX({
|
|
146
|
+
owner: 'example.com.',
|
|
147
|
+
preference: 10,
|
|
148
|
+
exchange: 'mail.example.com.',
|
|
149
|
+
ttl: 3600,
|
|
150
|
+
}).toBind()
|
|
151
|
+
// example.com 3600 IN MX 10 mail.example.com.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**When to use:** Generating zone files, displaying records for editing, exporting to BIND nameservers.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
#### 5. **Export to Tinydns** — Use `toTinydns()`
|
|
159
|
+
|
|
160
|
+
Convert to tinydns data file format:
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
new RR.A({
|
|
164
|
+
owner: 'example.com.',
|
|
165
|
+
address: '192.0.2.1',
|
|
166
|
+
ttl: 3600,
|
|
167
|
+
}).toTinydns()
|
|
168
|
+
// +example.com:192.0.2.1:3600::
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**When to use:** Generating tinydns data files, migrating to djbdns, or integrating with tinydns tooling.
|
|
172
|
+
|
|
173
|
+
---
|
|
97
174
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
175
|
+
#### 6. **Round-Trip Conversion**
|
|
176
|
+
|
|
177
|
+
Parse from one format, export to another:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
// tinydns → BIND
|
|
181
|
+
const fromTiny = RR.CAA.fromTinydns(
|
|
182
|
+
':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n',
|
|
183
|
+
)
|
|
184
|
+
console.log(fromTiny.toBind())
|
|
185
|
+
// ns1.example.com 3600 IN CAA 0 issue "http://letsencrypt.org"
|
|
101
186
|
```
|
|
102
187
|
|
|
103
|
-
|
|
188
|
+
**When to use:** DNS migrations, format conversions, tool interoperability.
|
|
189
|
+
|
|
190
|
+
---
|
|
104
191
|
|
|
105
|
-
|
|
192
|
+
### Manipulating Records
|
|
106
193
|
|
|
107
|
-
|
|
194
|
+
Use **setter methods** to modify validated records. Setter names follow the pattern `set` + `FieldName` (camelCased):
|
|
108
195
|
|
|
109
196
|
```js
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
197
|
+
const a = new RR.A({
|
|
198
|
+
owner: 'example.com.',
|
|
199
|
+
address: '192.0.2.1',
|
|
200
|
+
ttl: 3600,
|
|
201
|
+
})
|
|
113
202
|
|
|
114
|
-
|
|
115
|
-
|
|
203
|
+
a.setAddress('192.0.2.2')
|
|
204
|
+
a.setTtl(7200)
|
|
116
205
|
|
|
117
|
-
|
|
118
|
-
|
|
206
|
+
console.log(a.toBind())
|
|
207
|
+
// example.com 7200 IN A 192.0.2.2
|
|
119
208
|
```
|
|
120
209
|
|
|
121
|
-
|
|
210
|
+
Setters include validation. Invalid values throw with helpful error messages.
|
|
211
|
+
|
|
212
|
+
For a list of available setters, check `getFields('rdata')` for your record type:
|
|
122
213
|
|
|
123
214
|
```js
|
|
124
|
-
|
|
125
|
-
[
|
|
215
|
+
new RR.SSHFP(null).getFields('rdata')
|
|
216
|
+
// ['algorithm', 'fptype', 'fingerprint']
|
|
217
|
+
// So use: setSshfp(), setFptype(), setFingerprint()
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
126
221
|
|
|
127
|
-
|
|
128
|
-
[ 2782 ]
|
|
222
|
+
### Metadata Methods
|
|
129
223
|
|
|
130
|
-
|
|
131
|
-
|
|
224
|
+
Get information about record types:
|
|
225
|
+
|
|
226
|
+
#### `getFields([section])`
|
|
227
|
+
|
|
228
|
+
Get field names for a record type. Pass `'rdata'` to get only the custom fields:
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
new RR.A(null).getFields() // ['owner', 'ttl', 'class', 'type', 'address']
|
|
232
|
+
new RR.A(null).getFields('rdata') // ['address']
|
|
233
|
+
new RR.MX(null).getFields('rdata') // ['preference', 'exchange']
|
|
132
234
|
```
|
|
133
235
|
|
|
134
|
-
|
|
236
|
+
#### `getRFCs()`
|
|
135
237
|
|
|
136
|
-
|
|
238
|
+
Get RFC references for a record type:
|
|
137
239
|
|
|
138
240
|
```js
|
|
139
|
-
|
|
140
|
-
|
|
241
|
+
new RR.A(null).getRFCs() // [1035]
|
|
242
|
+
new RR.MX(null).getRFCs() // [1035, 2181, 7505]
|
|
243
|
+
new RR.SRV(null).getRFCs() // [2782]
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### `getCanonical()`
|
|
141
247
|
|
|
142
|
-
|
|
143
|
-
|
|
248
|
+
Get a record with all fields populated with default/canonical values:
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
new RR.AAAA(null).getCanonical()
|
|
252
|
+
// {
|
|
253
|
+
// owner: 'host.example.com.',
|
|
254
|
+
// address: '2001:0db8:0020:000a:0000:0000:0000:0004',
|
|
255
|
+
// class: 'IN',
|
|
256
|
+
// ttl: 3600,
|
|
257
|
+
// type: 'AAAA'
|
|
258
|
+
// }
|
|
144
259
|
```
|
|
145
260
|
|
|
146
|
-
|
|
261
|
+
#### `toJSON()` / `JSON.stringify()`
|
|
147
262
|
|
|
148
|
-
|
|
263
|
+
Serialize a record to a plain object:
|
|
149
264
|
|
|
150
265
|
```js
|
|
151
|
-
|
|
152
|
-
|
|
266
|
+
const a = new RR.A({ owner: 'example.com.', address: '192.0.2.1', ttl: 3600 })
|
|
267
|
+
JSON.stringify(a)
|
|
268
|
+
// {"owner":"example.com.","ttl":3600,"class":"IN","type":"A","address":"192.0.2.1"}
|
|
153
269
|
```
|
|
154
270
|
|
|
155
|
-
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### Advanced: Bypassing Validation
|
|
156
274
|
|
|
157
|
-
|
|
275
|
+
The `set()` method bypasses validation (use carefully):
|
|
158
276
|
|
|
159
277
|
```js
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
278
|
+
record.set('address', 'invalid-value')
|
|
279
|
+
// Works, but now the record is malformed — useful only for testing or low-level manipulation
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Note:** Validation is there to protect data integrity. Use at your own risk.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Browser & CDN
|
|
287
|
+
|
|
288
|
+
Use this module directly in browsers via CDN:
|
|
289
|
+
|
|
290
|
+
```html
|
|
291
|
+
<!DOCTYPE html>
|
|
292
|
+
<html>
|
|
293
|
+
<head>
|
|
294
|
+
<title>DNS Record Validator</title>
|
|
295
|
+
</head>
|
|
296
|
+
<body>
|
|
297
|
+
<h1>DNS Record Validator</h1>
|
|
298
|
+
<pre id="output"></pre>
|
|
299
|
+
|
|
300
|
+
<script type="module">
|
|
301
|
+
// Import from unpkg (or jsdelivr, esm.sh)
|
|
302
|
+
import * as RR from 'https://unpkg.com/@nictool/dns-resource-record@latest/dist/dns-rr.min.js'
|
|
303
|
+
|
|
304
|
+
// Use just like Node.js
|
|
305
|
+
const record = new RR.A({
|
|
306
|
+
owner: 'example.com.',
|
|
307
|
+
address: '192.0.2.1',
|
|
308
|
+
ttl: 3600,
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
document.getElementById('output').textContent = record.toBind()
|
|
312
|
+
</script>
|
|
313
|
+
</body>
|
|
314
|
+
</html>
|
|
164
315
|
```
|
|
165
316
|
|
|
166
|
-
|
|
317
|
+
**Available CDNs:**
|
|
167
318
|
|
|
168
|
-
|
|
319
|
+
- **unpkg:** `https://unpkg.com/@nictool/dns-resource-record/dist/dns-rr.min.js`
|
|
320
|
+
- **jsdelivr:** `https://cdn.jsdelivr.net/npm/@nictool/dns-resource-record/dist/dns-rr.min.js`
|
|
321
|
+
- **esm.sh:** `https://esm.sh/@nictool/dns-resource-record`
|
|
322
|
+
|
|
323
|
+
**Live example:** See [nictool.github.io/builder/](https://nictool.github.io/builder/) for an interactive DNS record editor using this library.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Important Concepts
|
|
328
|
+
|
|
329
|
+
### Domain Name Normalization
|
|
330
|
+
|
|
331
|
+
Domain owner names are:
|
|
332
|
+
|
|
333
|
+
- **Stored fully qualified** (absolute), e.g., `example.com.` not `example.com`
|
|
334
|
+
- **Normalized to lowercase** because:
|
|
335
|
+
- DNS is case-insensitive (RFC 4343, RFC 1035)
|
|
336
|
+
- This library enforces automatic duplicate suppression
|
|
337
|
+
- DNSSEC canonicalization requires it (RFC 4034)
|
|
338
|
+
- Wire format for most RRs requires lowercase
|
|
339
|
+
|
|
340
|
+
**Example:**
|
|
169
341
|
|
|
170
342
|
```js
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
'owner' => 'test.example.com',
|
|
174
|
-
'ttl' => 3600,
|
|
175
|
-
'class' => 'IN',
|
|
176
|
-
'type' => 'A',
|
|
177
|
-
'address' => 'oops'
|
|
178
|
-
}
|
|
343
|
+
new RR.A({ owner: 'EXAMPLE.COM', address: '192.0.2.1', ttl: 3600 })
|
|
344
|
+
// Automatically normalized to: 'example.com.'
|
|
179
345
|
```
|
|
180
346
|
|
|
181
|
-
|
|
347
|
+
### Relative vs Absolute Names
|
|
182
348
|
|
|
183
|
-
|
|
349
|
+
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.
|
|
350
|
+
|
|
351
|
+
### Export Options
|
|
352
|
+
|
|
353
|
+
The `toBind()` and `toMaraDNS()` methods accept an options object to customize output:
|
|
354
|
+
|
|
355
|
+
```js
|
|
356
|
+
record.toBind({ suppressTtl: true, suppressClass: true, relativeName: true })
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
See [dns-zone](https://github.com/NicTool/dns-zone) for full options documentation.
|
|
360
|
+
|
|
361
|
+
## Development
|
|
362
|
+
|
|
363
|
+
No external dependencies. Runs on node.js and modern browsers.
|
|
364
|
+
|
|
365
|
+
**Key scripts:**
|
|
366
|
+
|
|
367
|
+
- `npm test` — Run all tests with node's built-in test runner
|
|
368
|
+
- `npm run watch` — Run tests in watch mode during development
|
|
369
|
+
- `npm run lint` — Check code with ESLint
|
|
370
|
+
- `npm run format` — Auto-format with Prettier and fix linting issues
|
|
371
|
+
- `npm run build` — Regenerate browser bundle and README
|
|
372
|
+
- `npm run test:coverage` — Generate test coverage report
|
|
373
|
+
|
|
374
|
+
**Architecture:**
|
|
375
|
+
|
|
376
|
+
- **rr.js** — Base class with shared DNS logic and validation
|
|
377
|
+
- **rr/\*.js** — Individual RR type implementations
|
|
378
|
+
- **test/\*.js** — Comprehensive test suite for each RR type
|
|
379
|
+
|
|
380
|
+
## References
|
|
381
|
+
|
|
382
|
+
- [DNS Record Types (Wikipedia)](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
|
|
383
|
+
- [DNS Terminology (NicTool Dictionary)](https://nictool.github.io/Dictionary)
|
|
384
|
+
- [dns-zone](https://www.npmjs.com/package/@nictool/dns-zone) — Zone file operations
|
|
385
|
+
- [dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver) — Nameserver management
|
|
386
|
+
|
|
387
|
+
---
|
|
184
388
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
| **AAAA** | :white_check_mark: | :white_check_mark: |
|
|
194
|
-
| **CNAME** | :white_check_mark: | :white_check_mark: |
|
|
195
|
-
| **HTTPS** | :white_check_mark: | :white_check_mark: |
|
|
196
|
-
| **MX** | :white_check_mark: | :white_check_mark: |
|
|
197
|
-
| **NS** | :white_check_mark: | :white_check_mark: |
|
|
198
|
-
| **PTR** | :white_check_mark: | :white_check_mark: |
|
|
199
|
-
| **SRV** | :white_check_mark: | :white_check_mark: |
|
|
200
|
-
| **TXT** | :white_check_mark: | :white_check_mark: |
|
|
201
|
-
| _Less Common_ |
|
|
202
|
-
| **APL** | :white_check_mark: | :white_check_mark: |
|
|
203
|
-
| **CERT** | :white_check_mark: | :white_check_mark: |
|
|
204
|
-
| **DHCID** | :white_check_mark: | :white_check_mark: |
|
|
205
|
-
| **DNAME** | :white_check_mark: | :white_check_mark: |
|
|
206
|
-
| **HIP** | :white_check_mark: | :white_check_mark: |
|
|
207
|
-
| **KEY** | :white_check_mark: | :white_check_mark: |
|
|
208
|
-
| **KX** | :white_check_mark: | :white_check_mark: |
|
|
209
|
-
| **LOC** | :white_check_mark: | :white_check_mark: |
|
|
210
|
-
| **NAPTR** | :white_check_mark: | :white_check_mark: |
|
|
211
|
-
| **SOA** | :white_check_mark: | :white_check_mark: |
|
|
212
|
-
| **SVCB** | :white_check_mark: | :white_check_mark: |
|
|
213
|
-
| **TSIG** | :white_check_mark: | :white_check_mark: |
|
|
214
|
-
| **URI** | :white_check_mark: | :white_check_mark: |
|
|
215
|
-
| _Security_ |
|
|
216
|
-
| **CAA** | :white_check_mark: | :white_check_mark: |
|
|
217
|
-
| **IPSECKEY** | :white_check_mark: | :white_check_mark: |
|
|
218
|
-
| **OPENPGPKEY** | :white_check_mark: | :white_check_mark: |
|
|
219
|
-
| **SMIMEA** | :white_check_mark: | :white_check_mark: |
|
|
220
|
-
| **SSHFP** | :white_check_mark: | :white_check_mark: |
|
|
221
|
-
| **TLSA** | :white_check_mark: | :white_check_mark: |
|
|
222
|
-
| _DNSSEC_ |
|
|
223
|
-
| **DNSKEY** | :white_check_mark: | :white_check_mark: |
|
|
224
|
-
| **DS** | :white_check_mark: | :white_check_mark: |
|
|
225
|
-
| **NSEC** | :white_check_mark: | :white_check_mark: |
|
|
226
|
-
| **NSEC3** | :white_check_mark: | :white_check_mark: |
|
|
227
|
-
| **NSEC3PARAM** | :white_check_mark: | :white_check_mark: |
|
|
228
|
-
| **RRSIG** | :white_check_mark: | :white_check_mark: |
|
|
229
|
-
| _Deprecated_ |
|
|
230
|
-
| **NXT** | :white_check_mark: | :white_check_mark: |
|
|
231
|
-
| **SPF** | :white_check_mark: | :white_check_mark: |
|
|
232
|
-
| _Obsolete_ |
|
|
233
|
-
| **HINFO** | :white_check_mark: | :white_check_mark: |
|
|
234
|
-
| **RP** | :white_check_mark: | :white_check_mark: |
|
|
235
|
-
| **SIG** | :white_check_mark: | :white_check_mark: |
|
|
236
|
-
| **WKS** | :white_check_mark: | :white_check_mark: |
|
|
237
|
-
|
|
238
|
-
## TIPS
|
|
239
|
-
|
|
240
|
-
- Domain owner names are:
|
|
241
|
-
- stored fully qualified, aka absolute.
|
|
242
|
-
- normalized to lower case, because:
|
|
243
|
-
- DNS is case insensitive (see RFCs 4343, 1035, 1034)
|
|
244
|
-
- this library enforces duplicate suppression
|
|
245
|
-
- DNSSEC canonicalization (see RFC 4034)
|
|
246
|
-
- wire format for most RRs require it
|
|
247
|
-
- Master Zone File expansions exist in [dns-zone](https://github.com/NicTool/dns-zone)
|
|
248
|
-
- 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.
|
|
249
|
-
|
|
250
|
-
## SEE ALSO
|
|
251
|
-
|
|
252
|
-
- [Dictionary of DNS terms](https://nictool.github.io/web/Dictionary)
|
|
253
|
-
- [Wikipedia, List of DNS Record Types](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
|
|
254
|
-
- @nictool/[dns-zone](https://www.npmjs.com/package/@nictool/dns-zone)
|
|
255
|
-
- @nictool/[dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver)
|
|
256
|
-
|
|
257
|
-
## TODO
|
|
258
|
-
|
|
259
|
-
- [ ] export a web page for each RR type
|
|
260
|
-
|
|
261
|
-
## DEVELOP
|
|
262
|
-
|
|
263
|
-
- There are no dependencies. That's no accident.
|
|
264
|
-
- ES modules for use by node.js and browser
|
|
265
|
-
- Platform independence is a goal
|
|
266
|
-
- [x] CI tests are on linux, windows, and macos
|
|
389
|
+
[ci-img]: https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml/badge.svg
|
|
390
|
+
[ci-url]: https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml
|
|
391
|
+
[cov-img]: https://coveralls.io/repos/github/NicTool/dns-resource-record/badge.svg
|
|
392
|
+
[cov-url]: https://coveralls.io/github/NicTool/dns-resource-record
|
|
393
|
+
[bind-url]: https://www.isc.org/bind/
|
|
394
|
+
[knot-url]: https://www.knot-dns.cz
|
|
395
|
+
[nsd-url]: https://www.nlnetlabs.nl/projects/nsd/about/
|
|
396
|
+
[pdns-url]: https://www.powerdns.com/powerdns-authoritative-server
|