dns-response-validator
v1.4.4
Published
A production-ready TypeScript library for validating DNS query results and individual DNS records
Downloads
46
Maintainers
Readme
DNS Validator
A comprehensive TypeScript library for validating DNS query results and individual DNS records. Supports traditional DNS records (A, AAAA, MX, TXT, etc.) and DNSSEC records (DNSKEY, DS, RRSIG, NSEC, etc.) with enhanced error reporting and performance optimization.
Features
- ✅ Comprehensive DNS Record Support - Validates 19+ DNS record types including DNSSEC
- � DNSSEC Ready - Full support for DNSKEY, DS, RRSIG, NSEC, NSEC3, and SSHFP records
- � Enhanced Error Reporting - Detailed validation results with specific error messages and suggestions
- ⚡ Performance Optimized - Built-in caching, pre-validation, and performance tracking
- 🎯 Type Safe - Full TypeScript support with strict typing
- 🧪 Well Tested - Comprehensive test suite with 100% coverage
- � Excellent Documentation - Complete API docs with examples
Installation
npm install dns-response-validatoryarn add dns-response-validatorpnpm add dns-response-validatorQuick Start
Basic Validation
import { isARecord, isMXRecord, validateARecord } from 'dns-response-validator';
// Simple validation
const aRecord = { type: 'A', address: '192.168.1.1', ttl: 300 };
console.log(isARecord(aRecord)); // true
// Enhanced validation with detailed feedback
const result = validateARecord(aRecord);
console.log(result.isValid); // true
console.log(result.errors); // []
console.log(result.warnings); // []
import { isARecord, validateDNSRecord } from 'dns-response-validator';
// Validate an A record
const aRecord = {
type: 'A',
address: '192.168.1.1',
ttl: 300,
};
console.log(isARecord(aRecord)); // true
// Get detailed validation results
const validation = validateDNSRecord(aRecord);
console.log(validation);
// { isValid: true, errors: [], warnings: [] }Supported DNS Record Types
| Record Type | Function | Description |
| ----------- | ----------------- | ----------------------------------- |
| A | isARecord() | IPv4 address records |
| AAAA | isAAAARecord() | IPv6 address records |
| ANY | isANYRecord() | Any type of DNS record |
| CAA | isCAARecord() | Certificate Authority Authorization |
| CNAME | isCNAMERecord() | Canonical name records |
| MX | isMXRecord() | Mail exchange records |
| NAPTR | isNAPTRRecord() | Naming Authority Pointer |
| NS | isNSRecord() | Name server records |
| PTR | isPTRRecord() | Pointer records |
| SOA | isSOARecord() | Start of Authority records |
| SRV | isSRVRecord() | Service records |
| TLSA | isTLSARecord() | DANE TLSA records |
| TXT | isTXTRecord() | Text records |
Deep Imports & Tree Shaking
For optimal bundle size you can import only the modules you need using subpath exports (NodeNext / modern bundlers).
Examples:
// Core validators only
import { validateDNSRecord } from 'dns-response-validator/validators';
// DNSSEC utilities only
import { validateRRSIG, DNSSECAlgorithm } from 'dns-response-validator/dnssec';
// Performance helpers
import { trackPerformance } from 'dns-response-validator/performance';
// Types only (erased at compile time)
import type { ARecord, DNSRecord } from 'dns-response-validator/types';Available subpaths:
dns-response-validator/validatorsdns-response-validator/dnssecdns-response-validator/dnssec-validatorsdns-response-validator/enhanced-validatorsdns-response-validator/errorsdns-response-validator/performancedns-response-validator/utilsdns-response-validator/types(types only)
The package declares sideEffects only for the CLI entry, enabling aggressive tree-shaking for library code.
Dual CJS + ESM Builds
This package ships both CommonJS and native ES Module builds:
- CommonJS:
dist/*.jsreferenced via therequirecondition. - ESM:
dist/esm/*.jsreferenced via theimportcondition.
Most bundlers / Node (>=18) will automatically pick the optimal variant. You can explicitly force one:
// Force CommonJS
const { validateDNSRecord } = require('dns-response-validator');
// Force ESM (Node >=18 with type=module or .mjs)
import { validateDNSRecord } from 'dns-response-validator';Deep subpath imports also resolve to dual builds (e.g. dns-response-validator/validators).
Node.js dns Module Compatibility
This library now provides optional compatibility helpers for the core Node.js dns module API.
Key points:
- SOA records accept both internal field names (
primary,admin,expiration,minimum) and Node.js names (nsname,hostmaster,expire,minttl). Both sets are normalized vianormalizeSOA(). - TLSA records accept both (
usage,matchingType,certificate) and Node.js forms (certUsage,match,data). UsenormalizeTLSA()convenience helper. - ANY queries can be represented with a heterogeneous
recordsarray (similar todns.resolveAny) in addition to the legacyvaluefield. - Node DNS error code constants are exported as
NodeDNSErrorCodesalong with a type guardisNodeDNSErrorCode(). - Compatibility helpers are exported from
node-compatand re-exported at the root.
Examples
import {
normalizeSOA,
normalizeTLSA,
fromNodeTxt,
toNodeTxt,
fromNodeResolveAny,
NodeDNSErrorCodes,
} from 'dns-response-validator';
const soa = normalizeSOA({
type: 'SOA',
nsname: 'ns1.example.com',
hostmaster: 'hostmaster.example.com',
serial: 2024010101,
refresh: 3600,
retry: 600,
expire: 1209600,
minttl: 300,
});
const tlsa = normalizeTLSA({
type: 'TLSA',
certUsage: 3,
selector: 1,
match: 1,
data: 'abcdef1234',
});
console.log(NodeDNSErrorCodes.DNS_ENOTFOUND); // 'ENOTFOUND'
// TXT conversion
const nodeTxt = [['v=spf1', 'include:_spf.example.com', '~all']];
const internalTxt = fromNodeTxt(nodeTxt, 300);
const backToNode = toNodeTxt(internalTxt);
// ANY conversion
const anyNode = [
{ type: 'A', address: '127.0.0.1', ttl: 60 },
{ type: 'CNAME', value: 'example.com' },
];
const anyRecord = fromNodeResolveAny(anyNode);Supported DNS Error Codes
The following constants mirror node:dns and dns.promises error codes:
NODATA, FORMERR, SERVFAIL, NOTFOUND, NOTIMP, REFUSED, BADQUERY, BADNAME, BADFAMILY, BADRESP, CONNREFUSED, TIMEOUT, EOF, FILE, NOMEM, DESTRUCTION, BADSTR, BADFLAGS, NONAME, BADHINTS, NOTINITIALIZED, LOADIPHLPAPI, ADDRGETNETWORKPARAMS, CANCELLED.
Intentional Extensions
The library includes DNSSEC-related record validators (DNSKEY, DS, RRSIG, NSEC, NSEC3, SSHFP) that are not part of Node's core dns output. These are additive and do not affect Node compatibility.
Backward Compatibility
Previous field names still work; new Node-style names are additive. When both aliases are supplied the normalization helpers populate missing counterparts to create a fully dual-access shape.
API Reference
Individual Record Validation
Each DNS record type has its own validation function that returns a boolean:
import {
isARecord,
isAAAARecord,
isMXRecord,
isTXTRecord,
} from 'dns-response-validator';
// A Record (IPv4)
const aRecord = { type: 'A', address: '8.8.8.8', ttl: 300 };
console.log(isARecord(aRecord)); // true
// AAAA Record (IPv6)
const aaaaRecord = { type: 'AAAA', address: '2001:db8::1', ttl: 300 };
console.log(isAAAARecord(aaaaRecord)); // true
// MX Record
const mxRecord = {
type: 'MX',
priority: 10,
exchange: 'mail.example.com',
ttl: 300,
};
console.log(isMXRecord(mxRecord)); // true
// TXT Record
const txtRecord = {
type: 'TXT',
entries: ['v=spf1 include:_spf.google.com ~all'],
ttl: 300,
};
console.log(isTXTRecord(txtRecord)); // trueGeneric Record Validation
import { isDNSRecord, validateDNSRecord } from 'dns-response-validator';
const unknownRecord = {
type: 'A',
address: '192.168.1.1',
ttl: 300,
};
// Check if it's a valid DNS record of any type
console.log(isDNSRecord(unknownRecord)); // true
// Get detailed validation results
const result = validateDNSRecord(unknownRecord);
console.log(result);
// {
// isValid: true,
// errors: [],
// warnings: []
// }DNS Query Result Validation
Validate complete DNS query responses:
import { validateDNSResponse, DNSQueryResult } from 'dns-response-validator';
const dnsResponse: DNSQueryResult = {
question: {
name: 'example.com',
type: 'A',
class: 'IN',
},
answers: [
{
type: 'A',
address: '93.184.216.34',
ttl: 86400,
},
],
};
const validation = validateDNSResponse(dnsResponse);
console.log(validation);
// {
// isValid: true,
// errors: [],
// warnings: []
// }TypeScript Support
The library is written in TypeScript and provides comprehensive type definitions:
import {
ARecord,
MXRecord,
DNSRecord,
ValidationResult,
} from 'dns-response-validator';
// Strict typing for DNS records
const aRecord: ARecord = {
type: 'A',
address: '192.168.1.1',
ttl: 300,
};
const mxRecord: MXRecord = {
type: 'MX',
priority: 10,
exchange: 'mail.example.com',
ttl: 300,
};
// Union type for any DNS record
const record: DNSRecord = aRecord;
// Validation result typing
const result: ValidationResult = {
isValid: true,
errors: [],
warnings: [],
};Complex Record Examples
SOA Record
import { isSOARecord } from 'dns-response-validator';
const soaRecord = {
type: 'SOA',
primary: 'ns1.example.com',
admin: 'admin.example.com',
serial: 2023010101,
refresh: 86400,
retry: 7200,
expiration: 3600000,
minimum: 86400,
ttl: 86400,
};
console.log(isSOARecord(soaRecord)); // trueSRV Record
import { isSRVRecord } from 'dns-response-validator';
const srvRecord = {
type: 'SRV',
priority: 10,
weight: 20,
port: 443,
name: 'target.example.com',
ttl: 300,
};
console.log(isSRVRecord(srvRecord)); // trueCAA Record
import { isCAARecord } from 'dns-response-validator';
const caaRecord = {
type: 'CAA',
critical: 0,
issue: 'letsencrypt.org',
ttl: 86400,
};
console.log(isCAARecord(caaRecord)); // trueTLSA Record
import { isTLSARecord } from 'dns-response-validator';
const tlsaRecord = {
type: 'TLSA',
usage: 3,
selector: 1,
matchingType: 1,
certificate: 'abcdef1234567890abcdef1234567890',
ttl: 300,
};
console.log(isTLSARecord(tlsaRecord)); // trueError Handling
The library provides detailed error information for invalid records:
import { validateDNSRecord } from 'dns-response-validator';
const invalidRecord = {
type: 'A',
address: '999.999.999.999', // Invalid IP
ttl: 300,
};
const result = validateDNSRecord(invalidRecord);
console.log(result);
// {
// isValid: false,
// errors: ['Invalid A record structure or values'],
// warnings: []
// }Command Line Interface (CLI)
The DNS Validator includes a powerful CLI tool for validating DNS records and queries from the command line.
Installation
After installing the package globally:
npm install -g dns-response-validatorOr run directly with npx:
npx dns-response-validator --helpCLI Usage
Validate a Single Record
# Validate an A record
dns-response-validator record --type A --data '{"name":"example.com","address":"192.168.1.1","ttl":300}'
# Validate a record from file
dns-response-validator record --file record.json --format table
# Validate with strict mode
dns-response-validator record --file record.json --strict --format tableValidate DNS Query Response
# Validate a DNS query response
dns-response-validator query --file query.json --verbose
# Validate with custom output format
dns-response-validator query --data '{"answers":[...]}' --format csvBulk Validation
# Validate multiple records from file
dns-response-validator bulk --file records.json --format csv --output results.csv
# Strict mode bulk validation
dns-response-validator bulk --file records.json --strict --verboseCLI Options
--type <type>: DNS record type (A, AAAA, MX, TXT, etc.)--data <json>: DNS record/query data as JSON string--file <file>: Read data from JSON file--output <file>: Write results to file--format <format>: Output format (json, table, csv)--verbose: Show detailed output--strict: Enable strict validation mode
Sample Record Files
A Record (record.json):
{
"type": "A",
"name": "example.com",
"address": "192.168.1.1",
"ttl": 300
}DNS Query Response (query.json):
{
"question": {
"name": "example.com",
"type": "A",
"class": "IN"
},
"answers": [
{
"type": "A",
"name": "example.com",
"address": "192.168.1.1",
"ttl": 300
}
]
}Multiple Records (records.json):
[
{
"type": "A",
"name": "example.com",
"address": "192.168.1.1",
"ttl": 300
},
{
"type": "MX",
"name": "example.com",
"exchange": "mail.example.com",
"priority": 10,
"ttl": 3600
}
]CLI Examples
View all available examples:
dns-response-validator examplesDevelopment
Building the Project
npm run build # Build TypeScript to JavaScript
npm run build:watch # Build in watch mode
npm run clean # Clean dist directoryTesting
npm test # Run test suite
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage report
npm run test:ci # Run tests for CI (with coverage)Code Coverage
This project maintains high code coverage standards with 95%+ overall coverage. Coverage reports are automatically generated and uploaded to Codecov on every commit.
Coverage Thresholds:
- Global: 95% statements, 95% branches, 95% functions, 95% lines
- Core validators: 90% (critical validation logic)
- Enhanced validators: 100% (advanced features)
- DNSSEC modules: 100% (security-critical code)
Viewing Coverage Reports:
# Generate and view coverage report locally
npm run test:coverage
# Open HTML coverage report
# Windows
start coverage/lcov-report/index.html
# macOS
open coverage/lcov-report/index.html
# Linux
xdg-open coverage/lcov-report/index.htmlThe coverage configuration is defined in:
jest.config.js- Jest coverage settingscodecov.yml- Codecov configuration with component tracking
Code Quality
npm run typecheck # TypeScript type checking
npm run lint # ESLint code linting
npm run lint:fix # Fix linting issues automaticallyContributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built with TypeScript
- Uses validator.js for common validations
- Tested with Jest
Changelog
1.0.0
- Initial release
- Support for all major DNS record types
- Comprehensive TypeScript support
- Full test coverage
- Production-ready validation functions
ESM / CommonJS
After running npm run build:
CommonJS:
const lib = require('dns-validator-library');ESM:
import * as lib from 'dns-validator-library';
// or direct path (tests):
const m = await import('./dist/index.mjs');