@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +356 -199
  3. package/dist/dns-rr.cjs +7050 -0
  4. package/dist/dns-rr.min.js +26 -0
  5. package/dist/dns-rr.min.js.map +7 -0
  6. package/index.js +12 -11
  7. package/lib/binary.js +108 -0
  8. package/lib/bind.js +96 -0
  9. package/lib/dns-query.js +67 -0
  10. package/lib/tinydns.js +128 -44
  11. package/lib/wire.js +629 -0
  12. package/package.json +28 -8
  13. package/rr/TEMPLATE.js +124 -0
  14. package/rr/a.js +8 -48
  15. package/rr/aaaa.js +13 -80
  16. package/rr/apl.js +123 -27
  17. package/rr/caa.js +27 -50
  18. package/rr/cert.js +60 -81
  19. package/rr/cname.js +8 -59
  20. package/rr/dhcid.js +20 -30
  21. package/rr/dname.js +10 -32
  22. package/rr/dnskey.js +38 -32
  23. package/rr/ds.js +59 -54
  24. package/rr/hinfo.js +21 -40
  25. package/rr/hip.js +88 -26
  26. package/rr/https.js +28 -40
  27. package/rr/ipseckey.js +97 -18
  28. package/rr/key.js +39 -29
  29. package/rr/kx.js +16 -27
  30. package/rr/loc.js +42 -12
  31. package/rr/mx.js +17 -48
  32. package/rr/naptr.js +58 -33
  33. package/rr/ns.js +8 -36
  34. package/rr/nsec.js +89 -18
  35. package/rr/nsec3.js +62 -26
  36. package/rr/nsec3param.js +56 -53
  37. package/rr/nxt.js +57 -18
  38. package/rr/openpgpkey.js +24 -30
  39. package/rr/ptr.js +7 -47
  40. package/rr/rp.js +17 -32
  41. package/rr/rrsig.js +108 -75
  42. package/rr/sig.js +70 -45
  43. package/rr/smimea.js +33 -33
  44. package/rr/soa.js +31 -49
  45. package/rr/spf.js +15 -18
  46. package/rr/srv.js +28 -51
  47. package/rr/sshfp.js +35 -48
  48. package/rr/svcb.js +27 -40
  49. package/rr/tlsa.js +34 -34
  50. package/rr/tsig.js +87 -24
  51. package/rr/txt.js +77 -68
  52. package/rr/uri.js +19 -29
  53. package/rr/wks.js +154 -22
  54. package/rr.js +290 -109
  55. package/lib/readme.js +0 -84
package/README.md CHANGED
@@ -1,272 +1,429 @@
1
- [![Module Tests](https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml/badge.svg)](https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml)
2
- [![Coverage Status](https://coveralls.io/repos/github/NicTool/dns-resource-record/badge.svg?branch=master)](https://coveralls.io/github/NicTool/dns-resource-record?branch=master)
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
- ## SYNOPSIS
8
+ **Quick Links:** [Getting Started](#getting-started) | [API Reference](#api-reference) | [Browser/CDN](#browser--cdn) | [Supported Records](#supported-records) | [Contributing](#development)
9
9
 
10
- This module is used to:
10
+ ## Overview
11
11
 
12
- - validate well formedness and RFC compliance of DNS resource records
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
- | **RR format** | **import** | **export** |
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
- This package intends to import and export RFC compliant DNS resource records. Please [raise an issue](https://github.com/NicTool/dns-resource-record/issues) if a valid resource record fails to pass or an invalid resource record passes.
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 is for working with _individual_ Resource Records. For working with zones of RRs, use [dns-zone](https://github.com/NicTool/dns-zone).
22
+ **Scope:** This package handles individual Resource Records. For zone file operations, see [dns-zone](https://github.com/NicTool/dns-zone).
28
23
 
29
- ## USAGE
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
- Load the index for access to all RR types:
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
- ### EXAMPLES
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
- console.log(new RR.SOA(exampleRRs.SOA))
68
- SOA(11) [Map] {
69
- 'owner' => 'example.com.',
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
- Validate records by passing a properly formatted JS object to the record-specific class. To validate an A record:
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
- const validatedA = new RR.A(exampleRRs.A)
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
- Manipulate the validated record using pattern named setters:
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
- console.log(validatedA.toBind())
97
- test.example.com. 3600 IN A 192.0.2.127
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
- validatedA.setAddress('192.0.2.128')
100
- console.log(validatedA.toBind())
101
- test.example.com. 3600 IN A 192.0.2.128
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
- The setters are named: `set` + `Field`, where field is the resource record field name to modify. Multi-word names are camel cased, so a field named `Certificate Usage` has a setter named `setCertificateUsage`. The RFCs aren't always consistent regarding RR field names so aliases are permissible for interoperability.
154
+ **When to use:** Working with djbdns/tinydns configurations, or when parsing tinydns data files.
155
+
156
+ ---
105
157
 
106
- ## FUNCTIONS
158
+ #### 4. **Export to BIND** — Use `toBind()`
107
159
 
108
- ### getCanonical
160
+ Convert any validated record to BIND zone file format:
109
161
 
110
162
  ```js
111
- > console.log(new RR.AAAA(null).getCanonical())
112
- {
113
- owner: 'host.example.com.',
114
- address: '2001:0db8:0020:000a:0000:0000:0000:0004',
115
- class: 'IN',
163
+ new RR.MX({
164
+ owner: 'example.com.',
165
+ preference: 10,
166
+ exchange: 'mail.example.com.',
116
167
  ttl: 3600,
117
- type: 'AAAA'
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
- ### getFields
206
+ **When to use:** DNS migrations, format conversions, tool interoperability.
207
+
208
+ ---
209
+
210
+ ### Manipulating Records
122
211
 
123
- Get the field names for each RR type
212
+ Use **setter methods** to modify validated records. Setter names follow the pattern `set` + `FieldName` (camelCased):
124
213
 
125
214
  ```js
126
- > import * as RR from 'dns-resource-record'
127
- > new RR.A(null).getFields() // [ 'owner', 'ttl', 'class', 'type', 'address' ]
215
+ const a = new RR.A({
216
+ owner: 'example.com.',
217
+ address: '192.0.2.1',
218
+ ttl: 3600,
219
+ })
128
220
 
129
- > new RR.PTR(null).getFields() // [ 'owner', 'ttl', 'class', 'type', 'dname' ]
221
+ a.setAddress('192.0.2.2')
222
+ a.setTtl(7200)
130
223
 
131
- > new RR.SSHFP(null).getFields()
132
- // [ 'owner', 'ttl', 'class', 'type', 'algorithm', 'fptype', 'fingerprint' ]
224
+ console.log(a.toBind())
225
+ // example.com. 7200 IN A 192.0.2.2
133
226
  ```
134
227
 
135
- ### getRFCs
228
+ Setters include validation. Invalid values throw with helpful error messages.
136
229
 
137
- Get a list of RFCs references for each RR type
230
+ For a list of available setters, check `getFields('rdata')` for your record type:
138
231
 
139
232
  ```js
140
- > new RR.A(null).getRFCs() // [ 1035 ]
141
- > new RR.SRV(null).getRFCs() // [ 2782 ]
142
- > new RR.MX(null).getRFCs() // [ 1035, 2181, 7505 ]
233
+ new RR.SSHFP(null).getFields('rdata')
234
+ // ['algorithm', 'fptype', 'fingerprint']
235
+ // So use: setAlgorithm(), setFptype(), setFingerprint()
143
236
  ```
144
237
 
145
- ### toBind
238
+ ---
239
+
240
+ ### Metadata Methods
241
+
242
+ Get information about record types:
243
+
244
+ #### `getFields([section])`
146
245
 
147
- Validate a record and export to BIND format.
246
+ Get field names for a record type. Pass `'rdata'` to get only the custom fields:
148
247
 
149
248
  ```js
150
- console.log(new RR.A(exampleRRs.A).toBind())
151
- // test.example.com 3600 IN A 192.0.2.127
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
- console.log(new RR.AAAA(exampleRRs.AAAA).toBind())
154
- // test.example.com 3600 IN AAAA 2605:7900:20:a::4
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
- ### toTinydns
264
+ #### `getCanonical()`
158
265
 
159
- Validate a record and export to tinydns format:
266
+ Get a record with all fields populated with default/canonical values:
160
267
 
161
268
  ```js
162
- console.log(new RR.A(exampleRRs.A).toTinydns()) // +test.example.com:192.0.2.127:3600::
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
- ### set
279
+ #### `toJSON()` / `JSON.stringify()`
166
280
 
167
- The DNS validation checks can be bypassed entirely by using 'set':
281
+ Serialize a record to a plain object:
168
282
 
169
283
  ```js
170
- > validatedA.set('address', 'oops')
171
- A(5) [Map] {
172
- 'owner' => 'test.example.com',
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
- Consider this a "running with scissors" mode.
289
+ ---
181
290
 
182
- ### fromTinydns toBind
291
+ ### Advanced: Bypassing Validation
183
292
 
184
- Convert a tinydns line to BIND:
293
+ The `set()` method bypasses validation (use carefully):
185
294
 
186
295
  ```js
187
- console.log(new RR.CAA({
188
- tinyline: ':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n'
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
- ## Supported Records
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
- This module intends to support all current (ie, not officially deprecated) DNS RRs **and** all RRs that are in active use on the internet.
196
-
197
- PRs are welcome, especially PRs with tests.
198
-
199
- | **RR** | **BIND / RFC 1035** | **Tinydns** |
200
- | :------------: | :-----------------: | :----------------: |
201
- | _Common_ |
202
- | **A** | :white_check_mark: | :white_check_mark: |
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