diff --git a/index.js b/index.js index c3bb025..3768b20 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,19 @@ -for (const l of ['group', 'nameserver', 'permission', 'session', 'user', 'zone', 'zone_record']) { - module.exports[l] = require(`./lib/${l}`) +import * as group from './lib/group.js' +import * as nameserver from './lib/nameserver.js' +import * as permission from './lib/permission.js' +import * as session from './lib/session.js' +import * as user from './lib/user.js' +import * as zone from './lib/zone.js' +import * as zone_record from './lib/zone_record.js' + +export { group, nameserver, permission, session, user, zone, zone_record } + +export default { + group, + nameserver, + permission, + session, + user, + zone, + zone_record, } diff --git a/index.mjs b/index.mjs deleted file mode 100644 index c5278f4..0000000 --- a/index.mjs +++ /dev/null @@ -1,14 +0,0 @@ -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/index.test.js b/index.test.js index df87a71..14bb084 100644 --- a/index.test.js +++ b/index.test.js @@ -1,7 +1,10 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { createRequire } from 'node:module' -const schema = require('./index') +const require = createRequire(import.meta.url) + +import * as schema from './index.js' describe('index', function () { const testGroup = require('./lib/test/group.json') diff --git a/lib/group.js b/lib/group.js index b5ef89b..b83329e 100644 --- a/lib/group.js +++ b/lib/group.js @@ -1,61 +1,61 @@ -const Joi = require('joi') +import Joi from 'joi' -const shared = require('./shared') -const permission = require('./permission') +import * as shared from './shared.js' +import * as permission from './permission.js' -exports.id = Joi.number().integer().min(1).max(4294967295) +export const id = Joi.number().integer().min(1).max(4294967295) -exports.pid = shared.uint32 +export const pid = shared.uint32 -exports.name = Joi.string() +export const name = Joi.string() .min(3) .max(255) .pattern(new RegExp("^[a-zA-Z0-9 _.@'-]+$")) .pattern(new RegExp('^[a-zA-Z0-9]')) -exports.v3 = Joi.object({ - id: exports.id, - parent_gid: exports.pid, - name: exports.name.required(), +export const v3 = Joi.object({ + id: id, + parent_gid: pid, + name: name.required(), deleted: Joi.boolean(), has_children: Joi.boolean(), permission: permission.v3, }) // legacy group format -exports.v2 = Joi.object({ - nt_group_id: exports.id, - parent_group_id: exports.pid, - name: exports.name.required(), +export const v2 = Joi.object({ + nt_group_id: id, + parent_group_id: pid, + name: name.required(), deleted: Joi.boolean(), has_children: Joi.boolean(), permission: permission.v3, }) -exports.GET_req = Joi.object({ - id: exports.pid, - name: exports.name, +export const GET_req = Joi.object({ + id: pid, + name: name, deleted: Joi.boolean(), }) -exports.GET_res = Joi.object({ +export const GET_res = Joi.object({ group: Joi.object({ - id: exports.pid, - name: exports.name, - parent_gid: exports.pid, + id: pid, + name: name, + parent_gid: pid, deleted: Joi.boolean(), }), meta: shared.meta, }) -exports.POST = Joi.object({ - id: exports.id, - name: exports.name, - parent_gid: exports.pid, +export const POST = Joi.object({ + id: id, + name: name, + parent_gid: pid, deleted: Joi.boolean(), }) -exports.DELETE = Joi.object({ - id: exports.id, +export const DELETE = Joi.object({ + id: id, deleted: Joi.boolean(), }) diff --git a/lib/group.test.js b/lib/group.test.js index 778cebd..59946fc 100644 --- a/lib/group.test.js +++ b/lib/group.test.js @@ -1,7 +1,11 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { createRequire } from 'node:module' -const schema = require('./group').v3 +const require = createRequire(import.meta.url) + +import * as group from './group.js' +const schema = group.v3 const testGroup = require('./test/group.json') describe('group', function () { diff --git a/lib/nameserver.js b/lib/nameserver.js index 078d9f1..d9188d1 100644 --- a/lib/nameserver.js +++ b/lib/nameserver.js @@ -1,53 +1,53 @@ -const Joi = require('joi') +import Joi from 'joi' -const shared = require('./shared') +import * as shared from './shared.js' -exports.id = shared.uint16.min(0) +export const id = shared.uint16.min(0) -exports.name = Joi.string() +export const name = Joi.string() .min(2) .max(127) .domain({ allowFullyQualified: true, tlds: false }) .pattern(/\.$/) -exports.type = Joi.string().valid('bind', 'djbdns', 'knot', 'nsd', 'maradns', 'powerdns', 'dynect') +export const type = Joi.string().valid('bind', 'djbdns', 'knot', 'nsd', 'maradns', 'powerdns', 'dynect') -exports.remote_login = Joi.string().empty('').max(127) +export const remote_login = Joi.string().empty('').max(127) -exports.v3 = Joi.object({ - id: exports.id, +export const v3 = Joi.object({ + id: id, gid: shared.uint32.required(), - name: exports.name.required(), + name: name.required(), ttl: shared.ttl.required(), description: Joi.string().empty('').max(255), address: shared.ipv4.required(), address6: shared.ipv6.empty(''), - remote_login: exports.remote_login, + remote_login: remote_login, logdir: Joi.string().empty('').max(255), datadir: Joi.string().empty('').min(2).max(255), export: Joi.object({ interval: shared.uint16, serials: Joi.boolean(), status: Joi.string().empty('').max(255), - type: exports.type.required(), + type: type.required(), }), deleted: Joi.boolean(), }) -exports.GET_req = Joi.object({ - id: exports.id, - name: exports.name, +export const GET_req = Joi.object({ + id: id, + name: name, deleted: Joi.boolean(), }) -exports.GET_res = Joi.object({ - nameserver: Joi.array().items(exports.v3), +export const GET_res = Joi.object({ + nameserver: Joi.array().items(v3), meta: shared.meta, }) -exports.POST = exports.v3 +export const POST = v3 -exports.DELETE = Joi.object({ - id: exports.id, +export const DELETE = Joi.object({ + id: id, deleted: Joi.boolean(), }) diff --git a/lib/nameserver.test.js b/lib/nameserver.test.js index 19478a9..e84ac15 100644 --- a/lib/nameserver.test.js +++ b/lib/nameserver.test.js @@ -1,7 +1,11 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { createRequire } from 'node:module' -const schema = require('./nameserver').v3 +const require = createRequire(import.meta.url) + +import * as nameserver from './nameserver.js' +const schema = nameserver.v3 const testNS = require('./test/nameserver.json') describe('nameserver', function () { diff --git a/lib/permission.js b/lib/permission.js index 0dac807..e08a2e4 100644 --- a/lib/permission.js +++ b/lib/permission.js @@ -1,23 +1,23 @@ -const Joi = require('joi') +import Joi from 'joi' -const shared = require('./shared') +import * as shared from './shared.js' -exports.id = Joi.number().integer().min(1).max(4294967295) +export const id = Joi.number().integer().min(1).max(4294967295) -exports.v3 = Joi.object({ - id: exports.id, +export const v3 = Joi.object({ + id: id, name: Joi.string().empty(''), inherit: Joi.boolean(), self_write: Joi.boolean(), deleted: Joi.boolean(), group: Joi.object({ - id: exports.id, + id: id, write: Joi.boolean(), create: Joi.boolean(), delete: Joi.boolean(), }), user: Joi.object({ - id: exports.id, + id: id, write: Joi.boolean(), create: Joi.boolean(), delete: Joi.boolean(), @@ -42,19 +42,19 @@ exports.v3 = Joi.object({ }), }) -exports.POST = exports.v3 +export const POST = v3 -exports.GET_req = Joi.object({ - id: exports.id, +export const GET_req = Joi.object({ + id: id, deleted: Joi.boolean(), }) -exports.GET_res = Joi.object({ - permission: exports.v3, +export const GET_res = Joi.object({ + permission: v3, meta: shared.meta, }) -exports.DELETE = Joi.object({ - id: exports.id, +export const DELETE = Joi.object({ + id: id, deleted: Joi.boolean(), }) diff --git a/lib/session.js b/lib/session.js index 02dfae7..bc4336d 100644 --- a/lib/session.js +++ b/lib/session.js @@ -1,17 +1,17 @@ -const Joi = require('joi') +import Joi from 'joi' -const shared = require('./shared') -const group = require('./group') -const user = require('./user') +import * as shared from './shared.js' +import * as group from './group.js' +import * as user from './user.js' -exports.id = shared.uint32 +export const id = shared.uint32 -exports.POST = Joi.object({ +export const POST = Joi.object({ username: user.username.required(), password: user.password.required(), }) -exports.GET_res = Joi.object({ +export const GET_res = Joi.object({ user: user.v3, group: group.v3, session: Joi.object({ @@ -22,4 +22,4 @@ exports.GET_res = Joi.object({ meta: shared.meta, }) -exports.DELETE = Joi.object({}) +export const DELETE = Joi.object({}) diff --git a/lib/session.test.js b/lib/session.test.js index fd113ed..06e53a3 100644 --- a/lib/session.test.js +++ b/lib/session.test.js @@ -1,7 +1,7 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' -const schema = require('./session') +import * as schema from './session.js' describe('session', () => { describe('POST', function () { diff --git a/lib/shared.js b/lib/shared.js index 38795fb..5980ed0 100644 --- a/lib/shared.js +++ b/lib/shared.js @@ -1,6 +1,6 @@ -const Joi = require('joi') +import Joi from 'joi' -exports.meta = Joi.object({ +export const meta = Joi.object({ msg: Joi.string(), err: Joi.string(), api: Joi.object({ @@ -8,28 +8,28 @@ exports.meta = Joi.object({ }).unknown(), }).unknown() -exports.int8 = Joi.number().integer().min(-128).max(127) +export const int8 = Joi.number().integer().min(-128).max(127) -exports.uint8 = Joi.number().integer().min(0).max(255) +export const uint8 = Joi.number().integer().min(0).max(255) -exports.int16 = Joi.number().integer().min(-32768).max(32767) +export const int16 = Joi.number().integer().min(-32768).max(32767) -exports.uint16 = Joi.number().integer().min(0).max(65535) +export const uint16 = Joi.number().integer().min(0).max(65535) -exports.int32 = Joi.number().integer().min(-2147483648).max(2147483647) +export const int32 = Joi.number().integer().min(-2147483648).max(2147483647) -exports.uint32 = Joi.number().integer().min(0).max(4294967295) +export const uint32 = Joi.number().integer().min(0).max(4294967295) -exports.ipv4 = Joi.string() +export const ipv4 = Joi.string() .ip({ version: ['ipv4'], cidr: 'forbidden' }) .min(7) .max(15) -exports.ipv6 = Joi.string() +export const ipv6 = Joi.string() .ip({ version: ['ipv6'], cidr: 'forbidden' }) .min(2) .max(39) // Clarifications to the DNS specification: http://tools.ietf.org/html/rfc2181 // valid TTL is unsigned number from 0 to 2147483647 -exports.ttl = exports.int32.min(0) +export const ttl = int32.min(0) diff --git a/lib/shared.test.js b/lib/shared.test.js index b60a314..ce881e4 100644 --- a/lib/shared.test.js +++ b/lib/shared.test.js @@ -1,7 +1,7 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' -const shared = require('./shared') +import * as shared from './shared.js' describe('shared', function () { describe('ttl', function () { diff --git a/lib/user.js b/lib/user.js index 5c4ce18..5f415a5 100644 --- a/lib/user.js +++ b/lib/user.js @@ -1,15 +1,15 @@ -const Joi = require('joi') -const { joiPasswordExtendCore } = require('joi-password') +import Joi from 'joi' +import { joiPasswordExtendCore } from 'joi-password' const JoiPassword = Joi.extend(joiPasswordExtendCore) -const shared = require('./shared') -const group = require('./group') +import * as shared from './shared.js' +import * as group from './group.js' -exports.id = Joi.number().integer().min(1).max(4294967295) +export const id = Joi.number().integer().min(1).max(4294967295) -exports.username = Joi.string().min(3).max(50).pattern(new RegExp('^[a-zA-Z0-9 _.@-]+$', '')) +export const username = Joi.string().min(3).max(50).pattern(new RegExp('^[a-zA-Z0-9 _.@-]+$', '')) -exports.password = JoiPassword.string() +export const password = JoiPassword.string() .min(8) .max(30) .minOfSpecialCharacters(2) @@ -18,27 +18,27 @@ exports.password = JoiPassword.string() .minOfNumeric(2) .doesNotInclude(['password', 'abc', '123', 'asdf']) -exports.email = Joi.string().lowercase().email({ minDomainSegments: 2 }) +export const email = Joi.string().lowercase().email({ minDomainSegments: 2 }) // v3 API response -exports.v3 = Joi.object({ - id: exports.id, +export const v3 = Joi.object({ + id: id, first_name: Joi.string().min(1), last_name: Joi.string().min(1), - username: exports.username, - email: exports.email, - password: exports.password, + username: username, + email: email, + password: password, is_admin: Joi.boolean(), deleted: Joi.boolean(), }) -exports.GET_req = Joi.object({ - id: exports.id, +export const GET_req = Joi.object({ + id: id, deleted: Joi.boolean(), }) -exports.GET_res = Joi.object({ - user: Joi.array().items(exports.v3), +export const GET_res = Joi.object({ + user: Joi.array().items(v3), group: Joi.object({ id: group.id, name: group.name, @@ -46,30 +46,30 @@ exports.GET_res = Joi.object({ meta: shared.meta, }) -exports.POST = Joi.object({ - id: exports.id, +export const POST = Joi.object({ + id: id, gid: group.id, first_name: Joi.string().min(1), last_name: Joi.string().min(1), - username: exports.username, - email: exports.email, - password: exports.password, + username: username, + email: email, + password: password, is_admin: Joi.boolean(), }) -exports.DELETE = Joi.object({ - id: exports.id, +export const DELETE = Joi.object({ + id: id, }) -exports.v2 = Joi.object({ - nt_user_id: exports.id, +export const v2 = Joi.object({ + nt_user_id: id, nt_group_id: group.id, first_name: Joi.string().min(1), last_name: Joi.string().min(1), - email: exports.email, - username: exports.username, - password: exports.password, + email: email, + username: username, + password: password, is_admin: Joi.number().min(0).max(1), deleted: Joi.number().min(0).max(1), diff --git a/lib/user.test.js b/lib/user.test.js index 39ce23a..da3a93b 100644 --- a/lib/user.test.js +++ b/lib/user.test.js @@ -1,7 +1,10 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { createRequire } from 'node:module' -const schema = require('./user') +const require = createRequire(import.meta.url) + +import * as schema from './user.js' const userV2 = require('../test/fixtures/v2/user.json') const userV3 = require('./test/user.json') diff --git a/lib/zone.js b/lib/zone.js index 6456c8c..402ac3a 100644 --- a/lib/zone.js +++ b/lib/zone.js @@ -1,18 +1,18 @@ -const Joi = require('joi') +import Joi from 'joi' -const shared = require('./shared') +import * as shared from './shared.js' -exports.id = shared.uint32 +export const id = shared.uint32 -exports.zone = Joi.string().min(3).max(255) +export const zone = Joi.string().min(3).max(255) // .domain({ allowFullyQualified: true, allowUnderscore: true, tlds: false }) -exports.v3 = Joi.object({ - id: exports.id, +export const v3 = Joi.object({ + id: id, gid: shared.uint32.required(), - zone: exports.zone.required(), + zone: zone.required(), description: Joi.string().empty(''), @@ -39,9 +39,9 @@ exports.v3 = Joi.object({ deleted: Joi.boolean(), }) -exports.GET_req = Joi.object({ - id: exports.id, - zone: exports.zone, +export const GET_req = Joi.object({ + id: id, + zone: zone, search: Joi.string().max(255).allow(''), zone_like: Joi.string().max(255).allow(''), description_like: Joi.string().max(255).allow(''), @@ -52,14 +52,14 @@ exports.GET_req = Joi.object({ deleted: Joi.boolean(), }) -exports.GET_res = Joi.object({ - zone: Joi.array().items(exports.v3), +export const GET_res = Joi.object({ + zone: Joi.array().items(v3), meta: shared.meta, }) -exports.POST = exports.v3 +export const POST = v3 -exports.DELETE = Joi.object({ - id: exports.id, +export const DELETE = Joi.object({ + id: id, deleted: Joi.boolean(), }) diff --git a/lib/zone.test.js b/lib/zone.test.js index 61567a2..f3cc592 100644 --- a/lib/zone.test.js +++ b/lib/zone.test.js @@ -1,7 +1,11 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { createRequire } from 'node:module' -const schema = require('./zone').v3 +const require = createRequire(import.meta.url) + +import * as zone from './zone.js' +const schema = zone.v3 const testZone = require('./test/zone.json') describe('zone', function () { diff --git a/lib/zone_record.js b/lib/zone_record.js index 44049e7..67ad0f3 100644 --- a/lib/zone_record.js +++ b/lib/zone_record.js @@ -1,10 +1,10 @@ -const Joi = require('joi') +import Joi from 'joi' -const shared = require('./shared') +import * as shared from './shared.js' -exports.id = shared.uint32.min(1).required() +export const id = shared.uint32.min(1).required() -exports.owner = Joi.string() +export const owner = Joi.string() .min(1) .max(255) // .hostname({ @@ -15,12 +15,12 @@ exports.owner = Joi.string() // }) .required() -exports.v3 = Joi.object({ - id: exports.id, +export const v3 = Joi.object({ + id: id, zid: shared.uint32.min(1).required(), - owner: exports.owner, + owner: owner, ttl: shared.ttl.required(), @@ -68,30 +68,94 @@ exports.v3 = Joi.object({ algorithm: Joi.number().integer().min(0).max(255), + 'algorithm name': Joi.string().empty(''), + + 'apl rdata': Joi.string().empty(''), + + 'bit map': Joi.string().empty(''), + + certificate: Joi.string().empty(''), + + 'certificate association data': Joi.string().empty(''), + + 'certificate usage': [Joi.number(), Joi.string().empty('')], + + 'cert type': [Joi.number(), Joi.string().empty('')], + + cpu: Joi.string(), + cname: Joi.string(), data: Joi.string(), + digest: Joi.string().empty(''), + + 'digest type': [Joi.number(), Joi.string().empty('')], + description: Joi.string().empty(''), dname: Joi.string(), + error: [Joi.number(), Joi.string().empty('')], + + expire: [Joi.number(), Joi.string().empty('')], + exchange: Joi.string(), + exchanger: Joi.string().empty(''), + fingerprint: Joi.string(), flags: [Joi.number(), Joi.string().empty('')], + fptype: [Joi.number(), Joi.string().empty('')], + + fudge: [Joi.number(), Joi.string().empty('')], + gateway: Joi.string().empty(''), 'gateway type': Joi.number().empty(''), + 'hash algorithm': [Joi.number(), Joi.string().empty('')], + + hit: Joi.string().empty(''), + + iterations: [Joi.number(), Joi.string().empty('')], + + 'key tag': [Joi.number(), Joi.string().empty('')], + + labels: [Joi.number(), Joi.string().empty('')], + location: Joi.string().empty(''), + mac: Joi.string().empty(''), + + mbox: Joi.string().empty(''), + + 'matching type': [Joi.number(), Joi.string().empty('')], + + mname: Joi.string().empty(''), + + minimum: [Joi.number(), Joi.string().empty('')], + + 'next domain': Joi.string().empty(''), + + 'next hashed owner name': Joi.string().empty(''), + order: shared.uint16, + 'original id': [Joi.number(), Joi.string().empty('')], + + 'original ttl': [Joi.number(), Joi.string().empty('')], + + os: Joi.string(), + other: Joi.string().empty(''), + params: Joi.string().empty(''), + + 'pk algorithm': [Joi.number(), Joi.string().empty('')], + port: shared.uint16, precedence: shared.uint8, @@ -100,20 +164,58 @@ exports.v3 = Joi.object({ priority: shared.uint16, + protocol: [Joi.number(), Joi.string().empty('')], + + 'public key': Joi.string().empty(''), + publickey: Joi.string().empty(''), + refresh: [Joi.number(), Joi.string().empty('')], + regexp: Joi.string().empty(''), + 'rendezvous servers': Joi.string().empty(''), + replacement: Joi.string().empty(''), + retry: [Joi.number(), Joi.string().empty('')], + + rname: Joi.string().empty(''), + + salt: Joi.string().empty(''), + + selector: [Joi.number(), Joi.string().empty('')], + + serial: [Joi.number(), Joi.string().empty('')], + service: [Joi.number(), Joi.string().empty('')], + signature: Joi.string().empty(''), + + 'signature expiration': [Joi.number(), Joi.string().empty('')], + + 'signature inception': [Joi.number(), Joi.string().empty('')], + + 'signers name': Joi.string().empty(''), + tag: Joi.string(), target: Joi.string(), + 'target name': Joi.string().empty(''), + + 'time signed': [Joi.number(), Joi.string().empty('')], + timestamp: Joi.date(), + txt: Joi.string().empty(''), + + 'type bit map': Joi.string().empty(''), + + 'type bit maps': Joi.string().empty(''), + + 'type covered': Joi.string().empty(''), + weight: shared.uint16, value: Joi.string(), @@ -121,20 +223,20 @@ exports.v3 = Joi.object({ deleted: Joi.boolean(), }) -exports.GET_req = Joi.object({ +export const GET_req = Joi.object({ id: shared.uint32, zid: shared.uint32, deleted: Joi.boolean(), }) -exports.GET_res = Joi.object({ - zone_record: Joi.array().items(exports.v3), +export const GET_res = Joi.object({ + zone_record: Joi.array().items(v3), meta: shared.meta, }) -exports.POST = exports.v3 +export const POST = v3.fork(['id', 'ttl'], (schema) => schema.optional()) -exports.DELETE = Joi.object({ - id: exports.id, +export const DELETE = Joi.object({ + id: id, deleted: Joi.boolean(), }) diff --git a/lib/zone_record.test.js b/lib/zone_record.test.js index eb81b9b..858e8da 100644 --- a/lib/zone_record.test.js +++ b/lib/zone_record.test.js @@ -1,14 +1,25 @@ -const assert = require('node:assert/strict') -const { describe, it } = require('node:test') - -const schema = require('./zone_record').v3 +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { dirname } from 'node:path' +import { createRequire } from 'node:module' + +const require = createRequire(import.meta.url) +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +import * as zoneRecordSchema from './zone_record.js' +const schema = zoneRecordSchema.v3 +const postSchema = zoneRecordSchema.POST const testZR = require('./test/zone_record.json') describe('zone_record', function () { describe('id', function () { it(`accepts valid`, () => { const testCase = JSON.parse(JSON.stringify(testZR)) - const { error, value } = schema.validate(testCase) + const { error, value } = postSchema.validate(testCase) assert.ifError(error) assert.deepEqual(value, testCase) }) @@ -112,17 +123,62 @@ describe('zone_record', function () { assert.ok(/must be one of/.test(error.message)) }) } + + it('accepts HINFO with cpu and os', () => { + const testCase = JSON.parse(JSON.stringify(testZR)) + testCase.type = 'HINFO' + delete testCase.address + testCase.cpu = 'Intel' + testCase.os = 'Linux' + + const { error, value } = schema.validate(testCase) + assert.ifError(error) + assert.deepEqual(value, testCase) + }) }) describe('ttl', function () { - it(`rejects missing`, () => { + it(`accepts missing`, () => { const testCase = JSON.parse(JSON.stringify(testZR)) delete testCase.ttl - const { error, value } = schema.validate(testCase) + const { error, value } = postSchema.validate(testCase) - assert.strictEqual(error.message, '"ttl" is required') + assert.ifError(error) assert.deepEqual(value, testCase) }) }) + + describe('rdata schema coverage', function () { + const rrDir = path.resolve(__dirname, '../../dns-resource-record/rr') + const hasRrDir = fs.existsSync(rrDir) + + ;(hasRrDir ? it : it.skip)('includes every RR getRdataFields key', () => { + const rrFiles = fs.readdirSync(rrDir).filter((file) => file.endsWith('.js')) + + const rrFieldNames = new Set() + const methodRegex = /getRdataFields\s*\([^)]*\)\s*\{([\s\S]*?)\n\s*\}/g + const stringRegex = /['"]([^'"]+)['"]/g + + for (const file of rrFiles) { + const rrSource = fs.readFileSync(path.join(rrDir, file), 'utf8') + let methodMatch + + while ((methodMatch = methodRegex.exec(rrSource)) !== null) { + let stringMatch + while ((stringMatch = stringRegex.exec(methodMatch[1])) !== null) { + const field = stringMatch[1] + if (/^[A-Za-z][A-Za-z0-9\-\s]*$/.test(field)) { + rrFieldNames.add(field) + } + } + } + } + + const schemaKeys = Object.keys(zoneRecordSchema.v3.describe().keys) + const missing = [...rrFieldNames].filter((field) => !schemaKeys.includes(field)).sort() + + assert.deepEqual(missing, []) + }) + }) }) diff --git a/package.json b/package.json index 2383930..c65b82f 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,15 @@ "name": "@nictool/validate", "version": "0.8.5", "description": "NicTool Object Validation", + "type": "module", "files": [ "lib", "index.js", - "index.mjs", "CHANGELOG.md" ], "main": "index.js", "exports": { - ".": { - "import": "./index.mjs", - "require": "./index.js", - "default": "./index.js" - }, + ".": "./index.js", "./package.json": "./package.json", "./lib/*": "./lib/*" },