diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index aae5ab0..aaf3312 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,12 +1,8 @@
name: CI
on:
- push:
- branches-ignore:
- - 'dependabot/**' #avoid duplicates: run the PR, not the push
- tags-ignore:
- - 'v*' #avoid rerun existing commit on release
pull_request:
+ types: [opened, synchronize, reopened]
env:
CI: true
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index f79da52..7a266d6 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -1,13 +1,8 @@
name: publish
on:
- push:
- branches:
- - main
- paths:
- - package.json
- release:
- types: [published]
+ release:
+ types: [published]
env:
CI: true
diff --git a/.prettierrc.yml b/.prettierrc.yml
deleted file mode 100644
index 9b110b8..0000000
--- a/.prettierrc.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-trailingComma: 'all'
-semi: false
-singleQuote: true
diff --git a/.release b/.release
index 7307651..d106d83 160000
--- a/.release
+++ b/.release
@@ -1 +1 @@
-Subproject commit 73076513e83c2057a32515831b638771c15b1d83
+Subproject commit d106d83e69d5d8c99e4d6be4ba98ddde550d082b
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d5d1f7..d7a2efc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
### Unreleased
+### [0.8.3] - 2026-03-13
+
+- ns: NSD -> nsd
+- user: user is now an array
+- prettier: move config into package.json
+- zone: last publish can be all zeroes
+- zone_rec: expanded valid RR types & all the fields that go with them
+- ESM: dual export with wrapper
+- deps: bump all to latest
+
### [0.8.2] - 2025-04-08
- feat(zone_record): added GET, POST, and DELETE formats
@@ -77,13 +87,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
[0.5.0]: https://github.com/NicTool/validate/releases/tag/0.5.0
[0.6.0]: https://github.com/NicTool/validate/releases/tag/0.6.0
[0.6.1]: https://github.com/NicTool/validate/releases/tag/0.6.1
-[0.6.3]: https://github.com/NicTool/validate/releases/tag/0.6.3
+[0.6.3]: https://github.com/NicTool/validate/releases/tag/v0.6.3
[0.7.0]: https://github.com/NicTool/validate/releases/tag/0.7.0
-[0.7.1]: https://github.com/NicTool/validate/releases/tag/0.7.1
+[0.7.1]: https://github.com/NicTool/validate/releases/tag/v0.7.1
[0.7.2]: https://github.com/NicTool/validate/releases/tag/0.7.2
[0.7.3]: https://github.com/NicTool/validate/releases/tag/0.7.3
-[0.7.4]: https://github.com/NicTool/validate/releases/tag/0.7.4
-[0.8.0]: https://github.com/NicTool/validate/releases/tag/0.8.0
+[0.7.4]: https://github.com/NicTool/validate/releases/tag/v0.7.4
+[0.8.0]: https://github.com/NicTool/validate/releases/tag/v0.8.0
[0.8.1]: https://github.com/NicTool/validate/releases/tag/v0.8.1
[0.8.2]: https://github.com/NicTool/validate/releases/tag/v0.8.2
-[1.0.0]: https://github.com/NicTool/validate/releases/tag/1.0.0
+[0.8.3]: https://github.com/NicTool/validate/releases/tag/v0.8.3
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index bf1f31d..f3b0392 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,8 +1,8 @@
# Contributors
-This handcrafted artisinal software is brought to you by:
+This handcrafted artisanal software is brought to you by:
-| 
msimerson (21) |
+| 
msimerson (22) |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
this file is generated by [.release](https://github.com/msimerson/.release).
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 2c521da..8350eec 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,22 +1,13 @@
import globals from 'globals'
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
import js from '@eslint/js'
-import { FlatCompat } from '@eslint/eslintrc'
-
-const __filename = fileURLToPath(import.meta.url)
-const __dirname = path.dirname(__filename)
-const compat = new FlatCompat({
- baseDirectory: __dirname,
- recommendedConfig: js.configs.recommended,
- allConfig: js.configs.all,
-})
+import prettier from 'eslint-config-prettier'
export default [
{
- ignores: ['**/package-lock.json'],
+ ignores: ['**/package-lock.json', 'node_modules/**', '.release/**'],
},
- ...compat.extends('eslint:recommended', 'prettier'),
+ js.configs.recommended,
+ prettier,
{
languageOptions: {
globals: {
diff --git a/index.js b/index.js
index b260fd6..c3bb025 100644
--- a/index.js
+++ b/index.js
@@ -1,11 +1,3 @@
-for (const l of [
- 'group',
- 'nameserver',
- 'permission',
- 'session',
- 'user',
- 'zone',
- 'zone_record',
-]) {
+for (const l of ['group', 'nameserver', 'permission', 'session', 'user', 'zone', 'zone_record']) {
module.exports[l] = require(`./lib/${l}`)
}
diff --git a/index.mjs b/index.mjs
new file mode 100644
index 0000000..c5278f4
--- /dev/null
+++ b/index.mjs
@@ -0,0 +1,14 @@
+import { createRequire } from 'node:module'
+
+const require = createRequire(import.meta.url)
+const validate = require('./index.js')
+
+export default validate
+
+export const group = validate.group
+export const nameserver = validate.nameserver
+export const permission = validate.permission
+export const session = validate.session
+export const user = validate.user
+export const zone = validate.zone
+export const zone_record = validate.zone_record
diff --git a/lib/group.test.js b/lib/group.test.js
index 5bd1d2f..778cebd 100644
--- a/lib/group.test.js
+++ b/lib/group.test.js
@@ -28,10 +28,7 @@ describe('group', function () {
const { error, value } = schema.validate(testCase)
- assert.strictEqual(
- error.message,
- '"name" length must be at least 3 characters long',
- )
+ assert.strictEqual(error.message, '"name" length must be at least 3 characters long')
assert.deepEqual(value, testCase)
})
diff --git a/lib/nameserver.js b/lib/nameserver.js
index 784c2f0..078d9f1 100644
--- a/lib/nameserver.js
+++ b/lib/nameserver.js
@@ -10,15 +10,7 @@ exports.name = Joi.string()
.domain({ allowFullyQualified: true, tlds: false })
.pattern(/\.$/)
-exports.type = Joi.string().valid(
- 'bind',
- 'djbdns',
- 'knot',
- 'NSD',
- 'maradns',
- 'powerdns',
- 'dynect',
-)
+exports.type = Joi.string().valid('bind', 'djbdns', 'knot', 'nsd', 'maradns', 'powerdns', 'dynect')
exports.remote_login = Joi.string().empty('').max(127)
diff --git a/lib/nameserver.test.js b/lib/nameserver.test.js
index 6e14129..19478a9 100644
--- a/lib/nameserver.test.js
+++ b/lib/nameserver.test.js
@@ -35,10 +35,7 @@ describe('nameserver', function () {
})
}
- const errMsgs = [
- '"name" must be a valid hostname',
- '"name" must contain a valid domain name',
- ]
+ const errMsgs = ['"name" must be a valid hostname', '"name" must contain a valid domain name']
const invalid_names = [
'-bad_ns',
@@ -77,15 +74,7 @@ describe('nameserver', function () {
assert.deepEqual(value, testCase)
})
- for (const n of [
- 'bind',
- 'djbdns',
- 'knot',
- 'NSD',
- 'maradns',
- 'powerdns',
- 'dynect',
- ]) {
+ for (const n of ['bind', 'djbdns', 'knot', 'nsd', 'maradns', 'powerdns', 'dynect']) {
it(`accepts valid: ${n}`, () => {
const testCase = JSON.parse(JSON.stringify(testNS))
testCase.export.type = n
@@ -97,16 +86,7 @@ describe('nameserver', function () {
})
}
- for (const n of [
- 'cryptic',
- 'fuzzy',
- 'yitizg',
- 'bin',
- 'djbs',
- 'DJB',
- 'BIND',
- 'NT',
- ]) {
+ for (const n of ['cryptic', 'fuzzy', 'yitizg', 'bin', 'djbs', 'DJB', 'BIND', 'NT']) {
it(`rejects invalid: ${n}`, () => {
const testCase = JSON.parse(JSON.stringify(testNS))
testCase.export.type = n
@@ -115,7 +95,7 @@ describe('nameserver', function () {
assert.strictEqual(
error.message,
- '"export.type" must be one of [bind, djbdns, knot, NSD, maradns, powerdns, dynect]',
+ '"export.type" must be one of [bind, djbdns, knot, nsd, maradns, powerdns, dynect]',
)
assert.deepEqual(value, testCase)
})
diff --git a/lib/test/nameserver.json b/lib/test/nameserver.json
index f37c502..d030553 100644
--- a/lib/test/nameserver.json
+++ b/lib/test/nameserver.json
@@ -8,7 +8,7 @@
"logdir": "/foo",
"datadir": "/bar",
"export": {
- "type": "NSD",
+ "type": "nsd",
"interval": 0,
"serials": true,
"status": "last run:03-05 15:25
last cp :09-20 12:59"
diff --git a/lib/user.js b/lib/user.js
index 051585e..5c4ce18 100644
--- a/lib/user.js
+++ b/lib/user.js
@@ -7,10 +7,7 @@ const group = require('./group')
exports.id = Joi.number().integer().min(1).max(4294967295)
-exports.username = Joi.string()
- .min(3)
- .max(50)
- .pattern(new RegExp('^[a-zA-Z0-9 _.@-]+$', ''))
+exports.username = Joi.string().min(3).max(50).pattern(new RegExp('^[a-zA-Z0-9 _.@-]+$', ''))
exports.password = JoiPassword.string()
.min(8)
@@ -41,7 +38,7 @@ exports.GET_req = Joi.object({
})
exports.GET_res = Joi.object({
- user: exports.v3,
+ user: Joi.array().items(exports.v3),
group: Joi.object({
id: group.id,
name: group.name,
diff --git a/lib/user.test.js b/lib/user.test.js
index 693f602..39ce23a 100644
--- a/lib/user.test.js
+++ b/lib/user.test.js
@@ -38,16 +38,11 @@ describe('user', function () {
})
it('rejects too long', () => {
- const username =
- 'abcdefghijklmopqrstuvwxyzabcdefghijklmopqrstuvwxyzabcdefghijklmopqrstuvwxyz'
+ const username = 'abcdefghijklmopqrstuvwxyzabcdefghijklmopqrstuvwxyzabcdefghijklmopqrstuvwxyz'
const { error, value } = schema.username.validate(username)
- assert.ok(
- /length must be less than or equal to 50 characters long/.test(
- error.message,
- ),
- )
+ assert.ok(/length must be less than or equal to 50 characters long/.test(error.message))
assert.deepEqual(value, username)
})
diff --git a/lib/zone.js b/lib/zone.js
index 8795a03..c1bd6ee 100644
--- a/lib/zone.js
+++ b/lib/zone.js
@@ -4,18 +4,14 @@ const shared = require('./shared')
exports.id = shared.uint32
-exports.zone = Joi.string()
- .min(3)
- .max(255)
- .domain({ allowFullyQualified: true, tlds: false })
- .required()
+exports.zone = Joi.string().min(3).max(255).domain({ allowFullyQualified: true, tlds: false })
exports.v3 = Joi.object({
id: exports.id,
gid: shared.uint32.required(),
- zone: exports.zone,
+ zone: exports.zone.required(),
description: Joi.string().empty(''),
@@ -37,7 +33,7 @@ exports.v3 = Joi.object({
last_modified: Joi.date(),
- last_publish: Joi.date().allow('', null),
+ last_publish: Joi.date().allow('0000-00-00 00:00:00', '', null),
deleted: Joi.boolean(),
})
diff --git a/lib/zone.test.js b/lib/zone.test.js
index e15828d..6307cd2 100644
--- a/lib/zone.test.js
+++ b/lib/zone.test.js
@@ -37,10 +37,7 @@ describe('zone', function () {
const { error, value } = schema.validate(testCase)
// if (error) console.error(error.message)
- assert.strictEqual(
- error.message,
- '"zone" must contain a valid domain name',
- )
+ assert.strictEqual(error?.message, '"zone" must contain a valid domain name')
assert.deepEqual(value, testCase)
})
}
diff --git a/lib/zone_record.js b/lib/zone_record.js
index c65553f..905d1d6 100644
--- a/lib/zone_record.js
+++ b/lib/zone_record.js
@@ -20,14 +20,94 @@ exports.v3 = Joi.object({
ttl: shared.ttl.required(),
type: Joi.string()
- .valid('A', 'AAAA', 'PTR', 'MX', 'NS', 'CNAME', 'SRV')
+ .valid(
+ 'A',
+ 'AAAA',
+ 'CAA',
+ 'CERT',
+ 'CNAME',
+ 'DNAME',
+ 'DNSKEY',
+ 'DS',
+ 'HINFO',
+ 'HTTPS',
+ 'IPSECKEY',
+ 'KEY',
+ 'LOC',
+ 'MX',
+ 'NAPTR',
+ 'NS',
+ 'NSEC',
+ 'NSEC3',
+ 'NSEC3PARAM',
+ 'NXT',
+ 'OPENPGPKEY',
+ 'PTR',
+ 'RRSIG',
+ 'SIG',
+ 'SMIMEA',
+ 'SOA',
+ 'SPF',
+ 'SRV',
+ 'SSHFP',
+ 'SVCB',
+ 'TLSA',
+ 'TSIG',
+ 'TXT',
+ 'URI',
+ 'WKS',
+ )
.required(),
- address: Joi.string()
- .ip({ version: ['ipv4'], cidr: 'forbidden' })
- .min(7)
- .max(15)
- .required(),
+ address: Joi.string().min(2).max(39),
+
+ cname: Joi.string(),
+
+ data: Joi.string(),
+
+ description: Joi.string().empty(''),
+
+ dname: Joi.string(),
+
+ exchange: Joi.string(),
+
+ fingerprint: Joi.string(),
+
+ flags: [Joi.number(), Joi.string().empty('')],
+
+ gateway: Joi.string().empty(''),
+
+ 'gateway type': Joi.string().empty(''),
+
+ location: Joi.string().empty(''),
+
+ order: shared.uint16,
+
+ other: Joi.string().empty(''),
+
+ port: shared.uint16,
+
+ precedence: shared.uint8,
+
+ preference: shared.uint16,
+
+ priority: shared.uint16,
+
+ publickey: Joi.string().empty(''),
+
+ regexp: Joi.string().empty(''),
+
+ replacement: Joi.string().empty(''),
+
+ service: [Joi.number(), Joi.string().empty('')],
+
+ tag: Joi.string(),
+
+ target: Joi.string(),
+
+ weight: shared.uint16,
+
+ value: Joi.string(),
deleted: Joi.boolean(),
})
diff --git a/lib/zone_record.test.js b/lib/zone_record.test.js
index 3a7a8c9..8b2081e 100644
--- a/lib/zone_record.test.js
+++ b/lib/zone_record.test.js
@@ -73,10 +73,7 @@ describe('zone_record', function () {
const testCase = JSON.parse(JSON.stringify(testZR))
testCase.owner = owner
const { error } = schema.validate(testCase)
- assert.deepEqual(
- error.message,
- '"owner" must contain a valid domain name',
- )
+ assert.deepEqual(error.message, '"owner" must contain a valid domain name')
})
}
})
@@ -104,10 +101,7 @@ describe('zone_record', function () {
const testCase = JSON.parse(JSON.stringify(testZR))
testCase.type = type
const { error } = schema.validate(testCase)
- assert.deepEqual(
- error.message,
- '"type" must be one of [A, AAAA, PTR, MX, NS, CNAME, SRV]',
- )
+ assert.ok(/must be one of/.test(error.message))
})
}
})
diff --git a/package.json b/package.json
index c6e75e4..234913a 100644
--- a/package.json
+++ b/package.json
@@ -1,24 +1,35 @@
{
"name": "@nictool/validate",
- "version": "0.8.2",
+ "version": "0.8.3",
"description": "NicTool Object Validation",
"files": [
"lib",
"index.js",
+ "index.mjs",
"CHANGELOG.md"
],
"main": "index.js",
+ "exports": {
+ ".": {
+ "import": "./index.mjs",
+ "require": "./index.js",
+ "default": "./index.js"
+ },
+ "./package.json": "./package.json",
+ "./lib/*": "./lib/*"
+ },
"directories": {
"test": "test"
},
"scripts": {
"format:check": "npm run prettier; npm run lint",
"format": "npm run prettier -- --write && npm run lint --fix",
- "lint": "npx eslint **/*.js",
- "lint:fix": "npm run lint --fix",
+ "lint": "npx eslint .",
+ "lint:fix": "npx eslint --fix .",
"prettier": "npx prettier --ignore-path .gitignore --check .",
"prettier:fix": "npx prettier --ignore-path .gitignore --write .",
"test": "node --test",
+ "test:only": "node --test --test-only",
"versions": "npx dependency-version-checker check",
"versions:fix": "npx dependency-version-checker update",
"watch": "node --test --watch"
@@ -40,14 +51,19 @@
},
"homepage": "https://github.com/NicTool/validate#readme",
"devDependencies": {
- "@eslint/eslintrc": "^3.3.1",
- "eslint": "^9.24.0",
- "@eslint/js": "^10.0.0",
- "eslint-config-prettier": "^10.1.1",
- "globals": "^16.0.0"
+ "eslint": "^10.0.3",
+ "@eslint/js": "^10.0.1",
+ "eslint-config-prettier": "^10.1.8",
+ "globals": "^17.4.0"
},
"dependencies": {
- "joi": "^17.13.3",
- "joi-password": "^4.2.0"
+ "joi": "^18.0.2",
+ "joi-password": "^4.3.0"
+ },
+ "prettier": {
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "all",
+ "printWidth": 100
}
-}
+}
\ No newline at end of file