@nictool/dns-resource-record 1.2.0 → 1.2.2

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 (81) hide show
  1. package/.codeclimate.yml +25 -0
  2. package/.github/FUNDING.yml +3 -0
  3. package/.github/workflows/ci.yml +43 -0
  4. package/.github/workflows/codeql.yml +14 -0
  5. package/.github/workflows/publish.yml +16 -0
  6. package/.gitmodules +3 -0
  7. package/CHANGELOG.md +18 -0
  8. package/DEVELOP.md +9 -0
  9. package/README.md +6 -2
  10. package/eslint.config.mjs +41 -0
  11. package/index.js +6 -0
  12. package/package.json +12 -3
  13. package/rr/a.js +13 -3
  14. package/rr/aaaa.js +14 -4
  15. package/rr/caa.js +25 -13
  16. package/rr/cname.js +3 -3
  17. package/rr/dname.js +4 -4
  18. package/rr/dnskey.js +6 -11
  19. package/rr/ds.js +6 -8
  20. package/rr/hinfo.js +8 -6
  21. package/rr/https.js +62 -0
  22. package/rr/ipseckey.js +20 -9
  23. package/rr/key.js +2 -2
  24. package/rr/loc.js +4 -4
  25. package/rr/mx.js +15 -3
  26. package/rr/naptr.js +2 -2
  27. package/rr/ns.js +1 -1
  28. package/rr/nsec.js +2 -4
  29. package/rr/nsec3.js +6 -12
  30. package/rr/nsec3param.js +4 -9
  31. package/rr/nxt.js +2 -4
  32. package/rr/openpgpkey.js +7 -3
  33. package/rr/rrsig.js +3 -4
  34. package/rr/sig.js +1 -1
  35. package/rr/smimea.js +3 -5
  36. package/rr/soa.js +1 -2
  37. package/rr/spf.js +1 -1
  38. package/rr/srv.js +4 -4
  39. package/rr/sshfp.js +1 -1
  40. package/rr/svcb.js +64 -0
  41. package/rr/tlsa.js +10 -10
  42. package/rr/tsig.js +10 -2
  43. package/rr/txt.js +5 -5
  44. package/rr/uri.js +2 -2
  45. package/rr/wks.js +4 -3
  46. package/rr.js +32 -20
  47. package/test/a.js +75 -0
  48. package/test/aaaa.js +86 -0
  49. package/test/base.js +148 -0
  50. package/test/caa.js +111 -0
  51. package/test/cert.js +48 -0
  52. package/test/cname.js +40 -0
  53. package/test/dname.js +57 -0
  54. package/test/dnskey.js +45 -0
  55. package/test/ds.js +45 -0
  56. package/test/fake.js +34 -0
  57. package/test/hinfo.js +80 -0
  58. package/test/https.js +56 -0
  59. package/test/ipseckey.js +141 -0
  60. package/test/key.js +36 -0
  61. package/test/loc.js +75 -0
  62. package/test/mx.js +78 -0
  63. package/test/naptr.js +47 -0
  64. package/test/ns.js +56 -0
  65. package/test/nsec.js +37 -0
  66. package/test/nsec3.js +47 -0
  67. package/test/nsec3param.js +23 -0
  68. package/test/nxt.js +37 -0
  69. package/test/openpgpkey.js +85 -0
  70. package/test/ptr.js +56 -0
  71. package/test/rr.js +212 -0
  72. package/test/smimea.js +51 -0
  73. package/test/soa.js +99 -0
  74. package/test/spf.js +51 -0
  75. package/test/srv.js +101 -0
  76. package/test/sshfp.js +69 -0
  77. package/test/svcb.js +56 -0
  78. package/test/tinydns.js +163 -0
  79. package/test/tlsa.js +63 -0
  80. package/test/txt.js +82 -0
  81. package/test/uri.js +65 -0
@@ -0,0 +1,25 @@
1
+ checks:
2
+ return-statements:
3
+ enabled: false
4
+ similar-code:
5
+ enabled: false
6
+ file-lines:
7
+ config:
8
+ threshold: 500
9
+ method-lines:
10
+ config:
11
+ threshold: 50
12
+ method-complexity:
13
+ config:
14
+ threshold: 10
15
+
16
+ plugins:
17
+ eslint:
18
+ enabled: true
19
+ channel: 'eslint-8'
20
+ config:
21
+ config: '.eslintrc.yaml'
22
+
23
+ ratings:
24
+ paths:
25
+ - '**.js'
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: msimerson
@@ -0,0 +1,43 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ env:
8
+ CI: true
9
+
10
+ jobs:
11
+ lint:
12
+ uses: NicTool/.github/.github/workflows/lint.yml@main
13
+
14
+ coverage:
15
+ uses: NicTool/.github/.github/workflows/coverage.yml@main
16
+ secrets: inherit
17
+
18
+ test:
19
+ needs: get-lts
20
+ runs-on: ${{ matrix.os }}
21
+ strategy:
22
+ matrix:
23
+ os: [ubuntu-latest, windows-latest, macos-latest]
24
+ node-version: ${{ fromJson(needs.get-lts.outputs.active) }}
25
+ fail-fast: false
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-node@v4
29
+ name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
30
+ with:
31
+ node-version: ${{ matrix.node-version }}
32
+ - run: npm install
33
+ - run: npm test
34
+
35
+ get-lts:
36
+ needs: lint
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - id: get
40
+ uses: msimerson/node-lts-versions@v1
41
+ outputs:
42
+ lts: ${{ steps.get.outputs.lts }}
43
+ active: ${{ steps.get.outputs.active }}
@@ -0,0 +1,14 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ # The branches below must be a subset of the branches above
8
+ branches: [main]
9
+ schedule:
10
+ - cron: '18 7 * * 4'
11
+
12
+ jobs:
13
+ codeql:
14
+ uses: NicTool/.github/.github/workflows/codeql.yml@main
@@ -0,0 +1,16 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - package.json
9
+
10
+ env:
11
+ CI: true
12
+
13
+ jobs:
14
+ publish:
15
+ uses: NicTool/.github/.github/workflows/publish.yml@main
16
+ secrets: inherit
package/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule ".release"]
2
+ path = .release
3
+ url = https://github.com/msimerson/.release
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ Notable changes to this project are documented in this file.
4
4
 
5
5
  #### Unreleased
6
6
 
7
+ ### [1.2.2] - 2024-11-17
8
+
9
+ - dep(eslint): update to v9 & config
10
+ - chore: tighten up fromBind regex
11
+ - packaging tweaks (#43)
12
+
13
+ ### [1.2.1] - 2024-03-10
14
+
15
+ - fix(nsec3param): fixed setHash fname typo
16
+ - feat(SVCB,HTTPS): add record support (#29)
17
+ - feat(OPENGPGPKEY): improved bindline parser, added test
18
+ - feat(throwHelp): far more useful error messages (#41)
19
+ - feat(A,MX,AAAA,CAA,IPSECKEY): added getCanonical
20
+
7
21
  ### [1.2.0] - 2024-03-07
8
22
 
9
23
  - feat(index): export typeMap (lookup table for type to id)
@@ -286,3 +300,7 @@ Notable changes to this project are documented in this file.
286
300
  [1.1.5]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.5
287
301
  [1.1.6]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.6
288
302
  [1.1.8]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.8
303
+ [1.2.1]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.1
304
+ [1.2.2]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.2.2
305
+ [1.1.7]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.7
306
+ [1.2.0]: https://github.com/NicTool/dns-resource-record/releases/tag/1.2.0
package/DEVELOP.md ADDED
@@ -0,0 +1,9 @@
1
+ # Release process
2
+
3
+ In your local repo:
4
+
5
+ ```sh
6
+ git submodule update --init --recursive
7
+ ```
8
+
9
+ Read and follow the instructions in .release/README.md
package/README.md CHANGED
@@ -10,7 +10,7 @@ DNS resource record parser, validator, importer, and exporter.
10
10
  This module is used to:
11
11
 
12
12
  - validate well formedness and RFC compliance of DNS resource records
13
- - import RRs from and from the following formats:
13
+ - import RRs to and from the following formats:
14
14
 
15
15
  | **RR format** | **import** | **export** |
16
16
  | :------------------------------------------------------: | :----------------: | :----------------: |
@@ -20,7 +20,7 @@ This module is used to:
20
20
  | **MaraDNS** | | :white_check_mark: |
21
21
  | **JS** | :white_check_mark: | :white_check_mark: |
22
22
 
23
- 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 you a valid resource record fails to pass or an invalid resource record passes.
23
+ 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.
24
24
 
25
25
  This package is for working with _individual_ Resource Records. For working with zones of RRs, use [dns-zone](https://github.com/NicTool/dns-zone).
26
26
 
@@ -196,6 +196,7 @@ PRs are welcome, especially PRs with tests.
196
196
  | **DNSKEY** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
197
197
  | **DS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
198
198
  | **HINFO** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
199
+ | **HTTPS** | | | | |
199
200
  | **IPSECKEY** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
200
201
  | **KEY** | | | | |
201
202
  | **LOC** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
@@ -215,6 +216,7 @@ PRs are welcome, especially PRs with tests.
215
216
  | **SPF** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
216
217
  | **SRV** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
217
218
  | **SSHFP** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
219
+ | **SVCB** | | | | |
218
220
  | **TLSA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
219
221
  | **TSIG** | | | | |
220
222
  | **TXT** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
@@ -237,6 +239,8 @@ PRs are welcome, especially PRs with tests.
237
239
 
238
240
  - [Dictionary of DNS terms](https://nictool.github.io/web/Dictionary)
239
241
  - [Wikipedia, List of DNS Record Types](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
242
+ - @nictool/[dns-zone](https://www.npmjs.com/package/@nictool/dns-zone)
243
+ - @nictool/[dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver)
240
244
 
241
245
  ## TODO
242
246
 
@@ -0,0 +1,41 @@
1
+ import globals from 'globals'
2
+ import path from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import js from '@eslint/js'
5
+ import { FlatCompat } from '@eslint/eslintrc'
6
+
7
+ const __filename = fileURLToPath(import.meta.url)
8
+ const __dirname = path.dirname(__filename)
9
+ const compat = new FlatCompat({
10
+ baseDirectory: __dirname,
11
+ recommendedConfig: js.configs.recommended,
12
+ allConfig: js.configs.all,
13
+ })
14
+
15
+ export default [
16
+ {
17
+ languageOptions: {
18
+ ecmaVersion: 'latest',
19
+ globals: {
20
+ ...globals.node,
21
+ ...globals.browser,
22
+ ...globals.mocha,
23
+ },
24
+ sourceType: 'module',
25
+ },
26
+
27
+ rules: {
28
+ // 'no-undef': [ 'warn' ],
29
+ 'no-unused-vars': [
30
+ 'error',
31
+ {
32
+ args: 'none',
33
+ },
34
+ ],
35
+
36
+ 'dot-notation': 'error',
37
+ 'prefer-const': 'warn',
38
+ },
39
+ },
40
+ js.configs.recommended,
41
+ ]
package/index.js CHANGED
@@ -10,6 +10,7 @@ import DNAME from './rr/dname.js'
10
10
  import DNSKEY from './rr/dnskey.js'
11
11
  import DS from './rr/ds.js'
12
12
  import HINFO from './rr/hinfo.js'
13
+ import HTTPS from './rr/https.js'
13
14
  import IPSECKEY from './rr/ipseckey.js'
14
15
  import KEY from './rr/key.js'
15
16
  import LOC from './rr/loc.js'
@@ -29,6 +30,7 @@ import SOA from './rr/soa.js'
29
30
  import SPF from './rr/spf.js'
30
31
  import SRV from './rr/srv.js'
31
32
  import SSHFP from './rr/sshfp.js'
33
+ import SVCB from './rr/svcb.js'
32
34
  import TLSA from './rr/tlsa.js'
33
35
  import TSIG from './rr/tsig.js'
34
36
  import TXT from './rr/txt.js'
@@ -47,6 +49,7 @@ export {
47
49
  DNSKEY,
48
50
  DS,
49
51
  HINFO,
52
+ HTTPS,
50
53
  IPSECKEY,
51
54
  KEY,
52
55
  LOC,
@@ -66,6 +69,7 @@ export {
66
69
  SOA,
67
70
  SPF,
68
71
  SRV,
72
+ SVCB,
69
73
  TLSA,
70
74
  TSIG,
71
75
  TXT,
@@ -84,6 +88,7 @@ for (const c of [
84
88
  DNSKEY,
85
89
  DS,
86
90
  HINFO,
91
+ HTTPS,
87
92
  IPSECKEY,
88
93
  KEY,
89
94
  LOC,
@@ -103,6 +108,7 @@ for (const c of [
103
108
  SOA,
104
109
  SPF,
105
110
  SRV,
111
+ SVCB,
106
112
  TLSA,
107
113
  TSIG,
108
114
  TXT,
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "@nictool/dns-resource-record",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "DNS Resource Records",
5
5
  "main": "index.js",
6
+ "file": [
7
+ "lib",
8
+ "rr",
9
+ "CHANGELOG.md",
10
+ "rr.js"
11
+ ],
6
12
  "type": "module",
7
13
  "scripts": {
8
14
  "format:check": "npm run prettier; npm run lint",
9
15
  "format": "npm run prettier -- --write && npm run lint --fix",
10
- "lint": "npx eslint **/*.js",
16
+ "lint": "npx eslint@9 **/*.js",
11
17
  "lint:fix": "npm run lint -- --fix",
12
18
  "prettier": "npx prettier --ignore-path .gitignore --check .",
13
19
  "prettier:fix": "npx prettier --ignore-path .gitignore --write .",
@@ -39,6 +45,9 @@
39
45
  },
40
46
  "homepage": "https://github.com/NicTool/dns-resource-record#readme",
41
47
  "devDependencies": {
42
- "mocha": "^10.3.0"
48
+ "@eslint/js": "^9.15.0",
49
+ "eslint": "^9.15.0",
50
+ "globals": "^15.12.0",
51
+ "mocha": "^10.8.2"
43
52
  }
44
53
  }
package/rr/a.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
 
@@ -9,8 +9,8 @@ export default class A extends RR {
9
9
 
10
10
  /****** Resource record specific setters *******/
11
11
  setAddress(val) {
12
- if (!val) throw new Error('A: address is required')
13
- if (!net.isIPv4(val)) throw new Error('A address must be IPv4')
12
+ if (!val) this.throwHelp('A: address is required')
13
+ if (!net.isIPv4(val)) this.throwHelp('A address must be IPv4')
14
14
  this.set('address', val)
15
15
  }
16
16
 
@@ -30,6 +30,16 @@ export default class A extends RR {
30
30
  return 1
31
31
  }
32
32
 
33
+ getCanonical() {
34
+ return {
35
+ owner: 'host.example.com.',
36
+ class: 'IN',
37
+ ttl: 3600,
38
+ type: 'A',
39
+ address: '192.0.2.127',
40
+ }
41
+ }
42
+
33
43
  /****** IMPORTERS *******/
34
44
  fromTinydns(opts) {
35
45
  // +fqdn:ip:ttl:timestamp:lo
package/rr/aaaa.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
  import * as TINYDNS from '../lib/tinydns.js'
@@ -10,8 +10,8 @@ export default class AAAA extends RR {
10
10
 
11
11
  /****** Resource record specific setters *******/
12
12
  setAddress(val) {
13
- if (!val) throw new Error('AAAA: address is required')
14
- if (!net.isIPv6(val)) throw new Error(`AAAA: address must be IPv6 (${val})`)
13
+ if (!val) this.throwHelp('AAAA: address is required')
14
+ if (!net.isIPv6(val)) this.throwHelp(`AAAA: address must be IPv6 (${val})`)
15
15
 
16
16
  this.set('address', this.expand(val.toLowerCase())) // lower case: RFC 5952
17
17
  }
@@ -36,6 +36,16 @@ export default class AAAA extends RR {
36
36
  return 28
37
37
  }
38
38
 
39
+ getCanonical() {
40
+ return {
41
+ owner: 'host.example.com.',
42
+ address: '2001:0db8:0020:000a:0000:0000:0000:0004',
43
+ class: 'IN',
44
+ ttl: 3600,
45
+ type: 'A',
46
+ }
47
+ }
48
+
39
49
  /****** IMPORTERS *******/
40
50
  fromTinydns(opts) {
41
51
  const str = opts.tinyline
@@ -45,7 +55,7 @@ export default class AAAA extends RR {
45
55
  case ':':
46
56
  // GENERIC => :fqdn:28:rdata:ttl:timestamp:lo
47
57
  ;[fqdn, n, rdata, ttl, ts, loc] = str.substring(1).split(':')
48
- if (n != 28) throw new Error('AAAA fromTinydns, invalid n')
58
+ if (n != 28) this.throwHelp('AAAA fromTinydns, invalid n')
49
59
  ip = TINYDNS.octalToHex(rdata)
50
60
  .match(/([0-9a-fA-F]{4})/g)
51
61
  .join(':')
package/rr/caa.js CHANGED
@@ -11,7 +11,7 @@ export default class CAA extends RR {
11
11
  this.is8bitInt('CAA', 'flags', val)
12
12
 
13
13
  if (![0, 128].includes(val)) {
14
- throw new Error(`CAA flags ${val} not recognized, ${this.citeRFC()}`)
14
+ this.throwHelp(`CAA flags ${val} not recognized`)
15
15
  }
16
16
 
17
17
  this.set('flags', val)
@@ -19,12 +19,12 @@ export default class CAA extends RR {
19
19
 
20
20
  setTag(val) {
21
21
  if (typeof val !== 'string' || val.length < 1 || /[^a-z0-9]/.test(val))
22
- throw new Error(
23
- `CAA tag must be a sequence of ASCII letters and numbers in lowercase, ${this.citeRFC()}`,
22
+ this.throwHelp(
23
+ `CAA tag must be a sequence of ASCII letters and numbers in lowercase`,
24
24
  )
25
25
 
26
26
  if (!['issue', 'issuewild', 'iodef'].includes(val)) {
27
- throw new Error(`CAA tag ${val} not recognized: ${this.citeRFC()}`)
27
+ this.throwHelp(`CAA tag ${val} not recognized`)
28
28
  }
29
29
  this.set('tag', val)
30
30
  }
@@ -35,16 +35,14 @@ export default class CAA extends RR {
35
35
  if (this.isQuoted(val)) {
36
36
  val = val.replace(/^["']|["']$/g, '') // strip quotes
37
37
  } else {
38
- // if (/\s/.test(val)) throw new Error(`CAA value may not have spaces unless quoted: RFC 8659`)
38
+ // if (/\s/.test(val)) this.throwHelp(`CAA value may not have spaces unless quoted`)
39
39
  }
40
40
 
41
41
  // check if val starts with one of iodefSchemes
42
42
  if (this.get('tag') === 'iodef') {
43
43
  const iodefSchemes = ['mailto:', 'http:', 'https:']
44
44
  if (!iodefSchemes.filter((s) => val.startsWith(s)).length) {
45
- throw new Error(
46
- `CAA value must have valid iodefScheme prefix, ${this.citeRFC()}`,
47
- )
45
+ this.throwHelp(`CAA value must have valid iodefScheme prefix`)
48
46
  }
49
47
  }
50
48
 
@@ -71,11 +69,23 @@ export default class CAA extends RR {
71
69
  return 257
72
70
  }
73
71
 
72
+ getCanonical() {
73
+ return {
74
+ owner: 'example.com.',
75
+ ttl: 3600,
76
+ class: 'IN',
77
+ type: 'CAA',
78
+ flags: 0,
79
+ tag: 'issue',
80
+ value: 'http://letsencrypt.org',
81
+ }
82
+ }
83
+
74
84
  /****** IMPORTERS *******/
75
85
  fromTinydns(opts) {
76
86
  // CAA via generic, :fqdn:n:rdata:ttl:timestamp:lo
77
87
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
78
- if (n != 257) throw new Error('CAA fromTinydns, invalid n')
88
+ if (n != 257) this.throwHelp('CAA fromTinydns, invalid n')
79
89
 
80
90
  const flags = TINYDNS.octalToUInt8(rdata.substring(0, 4))
81
91
  const taglen = TINYDNS.octalToUInt8(rdata.substring(4, 8))
@@ -98,10 +108,12 @@ export default class CAA extends RR {
98
108
 
99
109
  fromBind(opts) {
100
110
  // test.example.com 3600 IN CAA flags, tags, value
101
- const fields = opts.bindline.match(
102
- /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+(\w+)\s+("[^"]+"|[^\s]+?)\s*$/i,
103
- )
104
- if (!fields) throw new Error(`unable to parse: ${opts.bindline}`)
111
+ const fields = opts.bindline
112
+ .trim()
113
+ .match(
114
+ /^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(CAA)\s+([0-9]+)\s+(\w+)\s+("[^"]+"|[\S]+?)$/i,
115
+ )
116
+ if (!fields) this.throwHelp(`unable to parse: ${opts.bindline}`)
105
117
 
106
118
  const [owner, ttl, c, type, flags, tag, value] = fields.slice(1)
107
119
  return new CAA({
package/rr/cname.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
 
@@ -12,10 +12,10 @@ export default class CNAME extends RR {
12
12
  // A <domain-name> which specifies the canonical or primary
13
13
  // name for the owner. The owner name is an alias.
14
14
 
15
- if (!val) throw new Error('CNAME: cname is required')
15
+ if (!val) this.throwHelp('CNAME: cname is required')
16
16
 
17
17
  if (net.isIPv4(val) || net.isIPv6(val))
18
- throw new Error(`CNAME: cname must be a FQDN: RFC 2181`)
18
+ this.throwHelp(`CNAME: cname must be a FQDN: RFC 2181`)
19
19
 
20
20
  if (!this.isFullyQualified('CNAME', 'cname', val)) return
21
21
  if (!this.isValidHostname('CNAME', 'cname', val)) return
package/rr/dname.js CHANGED
@@ -1,4 +1,4 @@
1
- import net from 'net'
1
+ import net from 'node:net'
2
2
 
3
3
  import RR from '../rr.js'
4
4
  import * as TINYDNS from '../lib/tinydns.js'
@@ -10,10 +10,10 @@ export default class DNAME extends RR {
10
10
 
11
11
  /****** Resource record specific setters *******/
12
12
  setTarget(val) {
13
- if (!val) throw new Error('DNAME: target is required')
13
+ if (!val) this.throwHelp('DNAME: target is required')
14
14
 
15
15
  if (net.isIPv4(val) || net.isIPv6(val))
16
- throw new Error(`DNAME: target must be a domain name, ${this.citeRFC()}`)
16
+ this.throwHelp(`DNAME: target must be a domain name`)
17
17
 
18
18
  this.isFullyQualified('DNAME', 'target', val)
19
19
  this.isValidHostname('DNAME', 'target', val)
@@ -42,7 +42,7 @@ export default class DNAME extends RR {
42
42
  fromTinydns(opts) {
43
43
  // DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo
44
44
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
45
- if (n != 39) throw new Error('DNAME fromTinydns, invalid n')
45
+ if (n != 39) this.throwHelp('DNAME fromTinydns, invalid n')
46
46
 
47
47
  return new DNAME({
48
48
  type: 'DNAME',
package/rr/dnskey.js CHANGED
@@ -13,8 +13,7 @@ export default class DNSKEY extends RR {
13
13
  this.is16bitInt('DNSKEY', 'flags', val)
14
14
 
15
15
  // the possible values are: 0, 256, and 257; RFC 4034
16
- if (![0, 256, 257].includes(val))
17
- throw new Error(`DNSKEY: flags invalid, ${this.citeRFC()}`)
16
+ if (![0, 256, 257].includes(val)) this.throwHelp(`DNSKEY: flags invalid`)
18
17
 
19
18
  this.set('flags', val)
20
19
  }
@@ -24,8 +23,7 @@ export default class DNSKEY extends RR {
24
23
  this.is8bitInt('DNSKEY', 'protocol', val)
25
24
 
26
25
  // The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3.
27
- if (![3].includes(val))
28
- throw new Error(`DNSKEY: protocol invalid, ${this.citeRFC()}`)
26
+ if (![3].includes(val)) this.throwHelp(`DNSKEY: protocol invalid`)
29
27
 
30
28
  this.set('protocol', val)
31
29
  }
@@ -37,16 +35,13 @@ export default class DNSKEY extends RR {
37
35
  // https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
38
36
  // 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1
39
37
  if (![...Array(16).keys(), 253, 254].includes(val))
40
- console.error(
41
- `DNSKEY: algorithm (${val}) not recognized, ${this.citeRFC()}`,
42
- )
38
+ console.error(`DNSKEY: algorithm (${val}) not recognized`)
43
39
 
44
40
  this.set('algorithm', val)
45
41
  }
46
42
 
47
43
  setPublickey(val) {
48
- if (!val)
49
- throw new Error(`DNSKEY: publickey is required, ${this.citeRFC()}`)
44
+ if (!val) this.throwHelp(`DNSKEY: publickey is required`)
50
45
 
51
46
  this.set('publickey', val)
52
47
  }
@@ -74,7 +69,7 @@ export default class DNSKEY extends RR {
74
69
  const match = opts.bindline.match(
75
70
  /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+\s*(.*?)\s*$/,
76
71
  )
77
- if (!match) throw new Error(`unable to parse DNSKEY: ${opts.bindline}`)
72
+ if (!match) this.throwHelp(`unable to parse DNSKEY: ${opts.bindline}`)
78
73
  const [owner, ttl, c, type, flags, protocol, algorithm, publickey] =
79
74
  match.slice(1)
80
75
 
@@ -92,7 +87,7 @@ export default class DNSKEY extends RR {
92
87
 
93
88
  fromTinydns(opts) {
94
89
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
95
- if (n != 48) throw new Error('DNSKEY fromTinydns, invalid n')
90
+ if (n != 48) this.throwHelp('DNSKEY fromTinydns, invalid n')
96
91
 
97
92
  const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
98
93
 
package/rr/ds.js CHANGED
@@ -10,9 +10,8 @@ export default class DS extends RR {
10
10
  /****** Resource record specific setters *******/
11
11
  setKeyTag(val) {
12
12
  // a 2 octet Key Tag field...in network byte order
13
- if (!val) throw new Error(`DS: key tag is required`)
14
- if (val.length > 2)
15
- throw new Error(`DS: key tag is too long, ${this.citeRFC()}`)
13
+ if (!val) this.throwHelp(`DS: key tag is required`)
14
+ if (val.length > 2) this.throwHelp(`DS: key tag is too long`)
16
15
 
17
16
  this.set('key tag', val)
18
17
  }
@@ -20,20 +19,19 @@ export default class DS extends RR {
20
19
  setAlgorithm(val) {
21
20
  // 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1
22
21
  if (![1, 2, 3, 4, 5, 253, 254].includes(val))
23
- throw new Error(`DS: algorithm invalid, ${this.citeRFC()}`)
22
+ this.throwHelp(`DS: algorithm invalid`)
24
23
 
25
24
  this.set('algorithm', val)
26
25
  }
27
26
 
28
27
  setDigestType(val) {
29
- if (![1, 2].includes(val))
30
- throw new Error(`DS: digest type invalid, ${this.citeRFC()}`)
28
+ if (![1, 2].includes(val)) this.throwHelp(`DS: digest type invalid`)
31
29
 
32
30
  this.set('digest type', val)
33
31
  }
34
32
 
35
33
  setDigest(val) {
36
- if (!val) throw new Error(`DS: digest is required, ${this.citeRFC()}`)
34
+ if (!val) this.throwHelp(`DS: digest is required`)
37
35
 
38
36
  this.set('digest', val)
39
37
  }
@@ -74,7 +72,7 @@ export default class DS extends RR {
74
72
 
75
73
  fromTinydns(opts) {
76
74
  const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':')
77
- if (n != 43) throw new Error('DS fromTinydns, invalid n')
75
+ if (n != 43) this.throwHelp('DS fromTinydns, invalid n')
78
76
 
79
77
  const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
80
78
 
package/rr/hinfo.js CHANGED
@@ -9,12 +9,12 @@ export default class HINFO extends RR {
9
9
 
10
10
  /****** Resource record specific setters *******/
11
11
  setCpu(val) {
12
- if (val.length > 255) throw new Error('HINFO cpu cannot exceed 255 chars')
12
+ if (val.length > 255) this.throwHelp('HINFO cpu cannot exceed 255 chars')
13
13
  this.set('cpu', val.replace(/^["']|["']$/g, ''))
14
14
  }
15
15
 
16
16
  setOs(val) {
17
- if (val.length > 255) throw new Error('HINFO os cannot exceed 255 chars')
17
+ if (val.length > 255) this.throwHelp('HINFO os cannot exceed 255 chars')
18
18
  this.set('os', val.replace(/^["']|["']$/g, ''))
19
19
  }
20
20
 
@@ -41,10 +41,12 @@ export default class HINFO extends RR {
41
41
  /****** IMPORTERS *******/
42
42
  fromBind(opts) {
43
43
  // test.example.com 3600 IN HINFO DEC-2060 TOPS20
44
- const match = opts.bindline.match(
45
- /([^\s]+)\s+([0-9]+)\s+(IN)\s+(HINFO)\s+("[^"]+"|[^\s]+)\s+("[^"]+"|[^\s]+)/i,
46
- )
47
- if (!match) throw new Error(`unable to parse HINFO: ${opts.bindline}`)
44
+ const match = opts.bindline
45
+ .trim()
46
+ .match(
47
+ /^([\S]+)\s+([0-9]{1,10})\s+(IN)\s+(HINFO)\s+("[^"]+"|[\S]+)\s+("[^"]+"|[\S]+)/i,
48
+ )
49
+ if (!match) this.throwHelp(`unable to parse HINFO: ${opts.bindline}`)
48
50
  const [owner, ttl, c, type, cpu, os] = match.slice(1)
49
51
 
50
52
  return new HINFO({