yq-dns
v1.0.14
Published
A promise-based DNS resolver that aggregates multiple DNS-over-HTTPS (DoH) providers with concurrency control
Maintainers
Readme
yq-dns
A comprehensive, promise-based DNS resolver library that aggregates multiple DNS-over-HTTPS (DoH) providers with advanced concurrency control, email validation, and flexible configuration. Built with TypeScript for maximum type safety and developer experience.
📋 Table of Contents
- Features
- Installation
- Quick Start
- DNS Providers
- Configuration
- API Reference
- DNS Record Types
- Email Validation
- TypeScript Support
- License
🚀 Features
YQ-DNS is designed to be the most comprehensive and reliable DNS resolution library for modern JavaScript applications. It combines multiple DNS-over-HTTPS providers with intelligent load balancing, advanced error handling, and extensive email validation capabilities to deliver enterprise-grade DNS resolution with exceptional performance and reliability.
- 🌐 Multiple DNS Providers: Google DoH, Cloudflare DoH, Quad9 DoH, and Node.js native DNS
- ⚡ High Performance: Concurrent requests with intelligent load balancing
- 🎯 Smart Provider Selection: Automatic failover and random selection
- 🔧 Flexible Configuration: Per-provider concurrency and rate limiting
- 📝 Full TypeScript Support: Complete type definitions and IntelliSense
- 🌍 Cross-Platform: Works with Node.js 18+, Deno, and Bun
- 📊 Complete DNS API: All standard DNS record types supported
- 📧 Email Validation: Comprehensive email domain validation and webmail detection
- 🛡️ Error Handling: Robust error handling with detailed error information
- 🔄 Automatic Retry: Built-in retry logic with exponential backoff
- 📈 Queue Management: Advanced queue management with rate limiter
- 🎛️ Runtime Configuration: Dynamic configuration updates without restart
📦 Installation
YQ-DNS is available as an npm package and can be installed using any modern JavaScript package manager. The library is built with zero dependencies for maximum compatibility and minimal bundle size, making it perfect for both server-side applications and edge computing environments.
Using npm:
npm install yq-dnsUsing Yarn:
yarn add yq-dnsUsing pnpm:
pnpm add yq-dnsRequirements:
- Node.js 18.0.0 or higher
- TypeScript 4.5+ (for TypeScript projects)
- Modern JavaScript environment with Promise support
🚀 Quick Start
Get started with YQ-DNS in seconds! The library offers two main approaches: standalone functions for simple DNS queries and the YqDns class for advanced configuration and control. Both approaches provide the same powerful DNS resolution capabilities with automatic provider selection and intelligent error handling.
Standalone Functions (Recommended for Simple Use Cases)
Standalone functions provide the quickest way to perform DNS lookups with sensible defaults and automatic provider selection:
// Using standalone functions (recommended for simple use cases)
import { resolve4, resolveMx, resolveAny } from 'yq-dns';
// Resolve A records
const addresses = await resolve4('example.com');
console.log(addresses); // ['93.184.216.34']
// Resolve MX records
const mxRecords = await resolveMx('example.com');
console.log(mxRecords); // [{ priority: 10, exchange: 'mail.example.com' }]
// Resolve with specific provider
const googleResult = await resolve4('example.com', undefined, 'google');YqDns Class (For Advanced Configuration)
The YqDns class provides fine-grained control over DNS providers, concurrency limits, timeouts, and retry behavior:
// Using YqDns class (for advanced configuration)
import { YqDns } from 'yq-dns';
const dns = new YqDns({
google: { enabled: true, limit: { concurrency: 10 } },
cloudflare: { enabled: true, limit: { concurrency: 5 } }
});
const addresses = await dns.resolve4('example.com');CommonJS Support
YQ-DNS fully supports CommonJS environments for maximum compatibility:
// CommonJS usage
const { resolve4, YqDns } = require('yq-dns');
const addresses = await resolve4('example.com');🌐 DNS Providers
YQ-DNS integrates with multiple DNS providers to ensure maximum reliability, performance, and flexibility. Each provider offers unique advantages and can be configured independently with custom settings for concurrency, timeouts, and retry behavior. The library automatically selects the best available provider or allows manual provider specification for specific use cases.
Native Provider
The native provider leverages Node.js's built-in DNS resolution capabilities, providing seamless integration with system DNS settings and local network configurations.
- Endpoint: Node.js built-in
dns/promisesmodule - Features: Supports all DNS methods including
lookup() - Use Case: Local/internal DNS resolution, system DNS settings
- Advantages: No external dependencies, respects system DNS configuration
- Best For: Internal networks, development environments, system-integrated applications
Google DoH (DNS-over-HTTPS)
Google's public DNS service provides enterprise-grade DNS resolution with global infrastructure and comprehensive DNSSEC validation.
- Endpoint:
https://dns.google/resolve - Features: DNSSEC validation, high reliability, global anycast network
- Use Case: Public DNS resolution with Google's infrastructure
- Advantages: Global CDN, excellent uptime, DNSSEC support, comprehensive logging
- Best For: Production applications, global services, DNSSEC-required environments
Cloudflare DoH (DNS-over-HTTPS)
Cloudflare's privacy-focused DNS service emphasizes user privacy with minimal logging and fast global resolution.
- Endpoint:
https://cloudflare-dns.com/dns-query - Features: Privacy-focused, minimal logging, malware protection
- Use Case: Privacy-conscious applications, consumer-facing services
- Advantages: Fast global network, strong privacy policy, built-in security features
- Best For: Privacy-sensitive applications, consumer products, GDPR-compliant services
Quad9 DoH (DNS-over-HTTPS)
Quad9's security-focused DNS service provides threat intelligence and malware blocking while maintaining user privacy.
- Endpoint:
https://dns.quad9.net/dns-query - Features: Security-focused, threat blocking, privacy protection
- Use Case: Security-sensitive applications, enterprise environments
- Advantages: Malware blocking, threat intelligence, non-profit organization, no user tracking
- Best For: Security-critical applications, enterprise networks, threat-aware environments
⚙️ Configuration
YQ-DNS provides extensive configuration options to fine-tune DNS resolution behavior according to your application's specific requirements. Each DNS provider can be configured independently with custom concurrency limits, rate limiting, timeouts, and retry policies. The configuration system supports both static initialization and dynamic runtime updates.
Basic Configuration Example
const dns = new YqDns({
google: {
enabled: true,
limit: { concurrency: 10, rps: 100 },
timeout: 5000,
retries: 3
},
cloudflare: {
enabled: true,
limit: { concurrency: 5, rps: 50 }
},
quad9: { enabled: false },
native: { enabled: true }
});Configuration Options
- enabled: Enable or disable the provider (boolean)
- limit.concurrency: Maximum concurrent requests per provider (number)
- limit.rps: Requests per second rate limit (number)
- timeout: Request timeout in milliseconds (number)
- retries: Number of retry attempts on failure (number)
- priority: Provider selection priority (number, higher = preferred)
Dynamic Configuration Updates
// Update configuration at runtime
dns.setConfig('google', { enabled: false });
dns.setConfigs({ cloudflare: { limit: { concurrency: 15 } } });📚 API Reference
The YQ-DNS API is designed for simplicity and flexibility, offering both class-based and functional approaches to DNS resolution. All methods return strongly-typed promises and support optional provider selection, custom timeouts, and advanced configuration options.
YqDns Class
The YqDns class provides a comprehensive DNS resolution interface with full configuration control and advanced features like provider management, concurrency control, and runtime configuration updates.
const dns = new YqDns(config?: YqConfig);
// Basic DNS resolution methods
dns.resolve4(hostname: string): Promise<string[]> // IPv4 addresses
dns.resolve6(hostname: string): Promise<string[]> // IPv6 addresses
dns.resolveMx(hostname: string): Promise<MxRecord[]> // Mail exchange records
dns.resolveTxt(hostname: string): Promise<string[][]> // Text records
dns.resolveCname(hostname: string): Promise<string[]> // Canonical name records
dns.resolveNs(hostname: string): Promise<string[]> // Name server records
dns.resolveSoa(hostname: string): Promise<SoaRecord> // Start of Authority
dns.resolvePtr(ip: string): Promise<string[]> // Reverse DNS lookup
dns.resolveSrv(hostname: string): Promise<SrvRecord[]> // Service records
dns.resolveAny(hostname: string): Promise<AnyRecord[]> // All available records
// Configuration methods
dns.setConfig(provider: string, config: ProviderConfig): void
dns.setConfigs(configs: Partial<YqConfig>): void
// Email validation
dns.emailValidator: EmailValidatorStandalone Functions
Standalone functions provide a lightweight alternative for simple DNS queries without the need for class instantiation. These functions use sensible defaults and automatic provider selection.
import { resolve4, resolveMx, resolveAny } from 'yq-dns';
// Use directly without creating a class instance
const addresses = await resolve4('example.com'); // Quick IPv4 resolution
const mxRecords = await resolveMx('example.com'); // Mail server lookup
const anyRecords = await resolveAny('example.com'); // Comprehensive DNS query
// With optional provider specification
const googleResult = await resolve4('example.com', undefined, 'google');
const cloudflareResult = await resolveMx('example.com', undefined, 'cloudflare');Method Parameters
Most DNS resolution methods accept the following parameters:
- hostname/ip: The domain name or IP address to resolve (string)
- options: Optional configuration object (varies by method)
- provider: Optional provider name for specific provider usage (string)
Return Types
All methods return strongly-typed promises with comprehensive type definitions for maximum TypeScript compatibility and IntelliSense support.
Email Validation
The Email Validation system provides comprehensive email address validation, domain analysis, and provider detection. It combines syntax validation, DNS lookups, and an extensive database of email providers to deliver accurate validation results with detailed metadata about the email address and its hosting provider.
EmailValidator Class
The EmailValidator class is the core component for email validation operations. It provides intelligent email analysis by checking syntax, validating domains through DNS resolution, detecting email providers, and identifying role-based addresses. The validator supports both basic and deep validation modes to accommodate different use cases and performance requirements.
validate(email: string, deep?: boolean): Promise<EmailResponse>
Performs comprehensive email validation and analysis, returning detailed information about the email address including provider detection, webmail availability, and role-based email identification.
Parameters:
email: Email address to validate (string)deep(optional): Enable deep validation with additional DNS lookups and extended checks (default: false)
Returns: EmailResponse object with one of the following structures:
Success Response Structure:
{
success: true,
data: {
provider: string, // Email provider name (e.g., "Gmail", "Outlook")
email: string, // Normalized email address
isFree: boolean, // Whether it's a free email provider domain
role: boolean, // Whether it's a role-based email (admin, support, etc.)
webmail?: string // Webmail URL if available
}
}Error Response Structure:
{
success: false,
type: 'Syntax' | 'Rejected' | 'Invalid' | 'Disposable' | 'Error',
email: string,
role: boolean, // Whether it's a role-based email
message?: string // Detailed error message (only present for 'Error' type)
}Basic Email Validation Examples
Simple Validation:
import { YqDns } from 'yq-dns';
const validator = YqDns.emailValidator;
// Basic email validation
const result = await validator.validate('[email protected]');
if (result.success) {
console.log('✅ Valid email');
console.log('Provider:', result.data.provider); // "Gmail"
console.log('Webmail:', result.data.webmail); // "https://mail.google.com"
console.log('Role email:', result.data.role); // false
} else {
console.log('❌ Invalid email:', result.type);
}Deep Validation Mode:
// Enable deep validation for thorough analysis
const deepResult = await validator.validate('[email protected]', true);
if (deepResult.success) {
console.log('Provider:', deepResult.data.provider);
console.log('Is role-based:', deepResult.data.role); // likely true for "admin"
}Provider Detection Examples
Major Email Providers:
// Gmail detection
const gmailResult = await validator.validate('[email protected]');
console.log(gmailResult.data?.provider); // "Gmail"
// Outlook detection
const outlookResult = await validator.validate('[email protected]');
console.log(outlookResult.data?.provider); // "Outlook"
// Yahoo detection
const yahooResult = await validator.validate('[email protected]');
console.log(yahooResult.data?.provider); // "Yahoo"
// Corporate email detection
const corpResult = await validator.validate('[email protected]');
console.log(corpResult.data?.provider); // "Microsoft"Role-Based Email Detection
Identifying Role-Based Addresses:
// Common role-based emails
const roleEmails = [
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]'
];
for (const email of roleEmails) {
const result = await validator.validate(email);
if (result.success && result.data.role) {
console.log(`${email} is a role-based email`);
}
}Webmail Detection and Access
Webmail URL Extraction:
// Get webmail URLs for popular providers
const webmailEmails = [
'[email protected]', // https://mail.google.com
'[email protected]', // https://outlook.live.com
'[email protected]', // https://mail.yahoo.com
'[email protected]' // https://www.icloud.com/mail
];
for (const email of webmailEmails) {
const result = await validator.validate(email);
if (result.success && result.data.webmail) {
console.log(`${email} -> ${result.data.webmail}`);
}
}Batch Email Validation
Validating Multiple Emails:
async function validateEmailBatch(emails: string[]) {
const results = await Promise.allSettled(
emails.map(email => validator.validate(email))
);
return emails.map((email, index) => {
const result = results[index];
if (result.status === 'fulfilled' && result.value.success) {
return {
email,
valid: true,
provider: result.value.data.provider,
role: result.value.data.role,
webmail: result.value.data.webmail
};
} else {
return {
email,
valid: false,
error: result.status === 'fulfilled' ? result.value.type : 'validation_failed'
};
}
});
}
// Usage example
const emailList = [
'[email protected]',
'invalid.email',
'[email protected]',
'[email protected]'
];
const batchResults = await validateEmailBatch(emailList);
console.log('Batch validation results:', batchResults);Error Handling and Response Types
Comprehensive Error Handling:
async function handleEmailValidation(email: string) {
try {
const result = await validator.validate(email);
if (result.success) {
return {
status: 'valid',
data: result.data
};
} else {
// Handle different error types
switch (result.type) {
case 'Syntax':
return { status: 'syntax_error', message: 'Invalid email format' };
case 'Invalid':
return { status: 'invalid_domain', message: 'Domain does not exist' };
case 'Rejected':
return { status: 'rejected', message: 'Email rejected by provider' };
case 'Disposable':
return { status: 'disposable', message: 'Disposable email address' };
case 'Error':
return { status: 'validation_error', message: result.message };
default:
return { status: 'unknown_error', message: 'Validation failed' };
}
}
} catch (error) {
return {
status: 'exception',
message: error instanceof Error ? error.message : 'Unexpected error'
};
}
}
// Usage
const validationResult = await handleEmailValidation('[email protected]');
console.log(validationResult);Advanced Use Cases
Email Domain Analysis:
async function analyzeEmailDomain(email: string) {
const result = await validator.validate(email, true); // Deep validation
if (result.success) {
const domain = email.split('@')[1];
return {
email: result.data.email,
domain,
provider: result.data.provider,
hasWebmail: !!result.data.webmail,
webmailUrl: result.data.webmail,
isRoleBased: result.data.role,
isPersonal: ['Gmail', 'Yahoo', 'Outlook', 'iCloud'].includes(result.data.provider),
isCorporate: !['Gmail', 'Yahoo', 'Outlook', 'iCloud'].includes(result.data.provider)
};
} else {
return {
email,
valid: false,
errorType: result.type,
errorMessage: result.message
};
}
}
const analysis = await analyzeEmailDomain('[email protected]');
console.log('Email analysis:', analysis);Additional EmailValidator Methods
The EmailValidator class provides several utility methods for email validation and manipulation:
isEmail(email: string): boolean
Performs advanced email format validation with structural constraints.
Validation Rules:
- Maximum 35 characters for the local part
- Maximum 3 hyphens in the local part
- Maximum 3 dots in the local part
- Maximum 3 dots in the domain part
- Maximum 2 hyphens in the domain part
- Maximum 55 total characters in the email address
- Local part must be at least 2 characters
- Domain part must be at least 5 characters
Example:
const validator = EmailValidator.create();
validator.isEmail("[email protected]"); // true
validator.isEmail("[email protected]"); // false (domain too short)
validator.isEmail("[email protected]"); // falseisFreeDomain(email_or_domain: string): boolean
Checks if an email address or domain belongs to a free email provider (Gmail, Yahoo, Outlook, etc.).
Example:
validator.isFreeDomain('[email protected]'); // true
validator.isFreeDomain('gmail.com'); // true
validator.isFreeDomain('[email protected]'); // falseisDisposable(email: string): boolean
Checks if an email address is from a known disposable/temporary email provider.
Example:
validator.isDisposable('[email protected]'); // true
validator.isDisposable('[email protected]'); // falseisJson(input: string): string[] | null
Validates if a string is a JSON array of valid email addresses.
Returns: Array of valid emails if successful, null otherwise.
Example:
validator.isJson('["[email protected]", "[email protected]"]');
// Returns: ["[email protected]", "[email protected]"]
validator.isJson('["foo", 1, null]'); // Returns: null
validator.isJson('not json'); // Returns: nullextractEmails(input: string[]): string[]
Extracts valid email addresses from various input formats including:
- Plain email addresses
- Comma-separated values
- URL-encoded strings (automatically decoded)
- JSON arrays
Example:
// Single email
validator.extractEmails(["[email protected]"]);
// Returns: ["[email protected]"]
// Comma-separated emails
validator.extractEmails(["[email protected],[email protected]"]);
// Returns: ["[email protected]", "[email protected]"]
// URL-encoded
validator.extractEmails(["user%40example.com,test%40domain.com"]);
// Returns: ["[email protected]", "[email protected]"]
// JSON array
validator.extractEmails(['["[email protected]", "[email protected]"]']);
// Returns: ["[email protected]", "[email protected]"]
// Mixed formats
validator.extractEmails([
"[email protected]",
"[email protected],[email protected]",
'["[email protected]"]'
]);
// Returns: ["[email protected]", "[email protected]", "[email protected]", "[email protected]"]getProviderWebmailUrl(provider: ProviderName): string | null
getProviderWebmailUrl(provider: ProviderName, domainOrEmail: string): string | null
getProviderWebmailUrl(domainOrEmail: string): string | null
Retrieves the webmail URL for a given email provider. Supports multiple overloaded signatures for flexibility.
Parameters:
provider- Provider name (e.g., "Gmail", "Outlook") or domain/emaildomainOrEmail(optional) - Domain name or full email address
Returns: Webmail URL string if found, null otherwise.
Example:
// Using provider name
validator.getProviderWebmailUrl('Gmail');
// Returns: "https://mail.google.com"
// Using domain
validator.getProviderWebmailUrl('outlook.com');
// Returns: "https://outlook.live.com"
// Using email address
validator.getProviderWebmailUrl('[email protected]');
// Returns: "https://mail.yahoo.com"
// Using provider name with domain
validator.getProviderWebmailUrl('Gmail', 'google.com');
// Returns: "https://mail.google.com"
// Unknown provider
validator.getProviderWebmailUrl('unknown-provider.com');
// Returns: null🗂️ DNS Record Types
YQ-DNS supports all standard DNS record types with comprehensive parsing and type-safe return values. Each record type is optimized for specific use cases, from basic domain resolution to advanced service discovery and email routing. The library automatically handles record parsing and provides structured data objects for easy consumption.
| Record Type | Description | Use Cases | Return Type |
|-------------|-------------|-----------|-------------|
| A | IPv4 address records | Web hosting, basic domain resolution | string[] |
| AAAA | IPv6 address records | Modern networking, dual-stack configurations | string[] |
| MX | Mail exchange records | Email routing, mail server discovery | MxRecord[] |
| TXT | Text records | Domain verification, SPF, DKIM, configuration | string[][] |
| CNAME | Canonical name records | Domain aliases, CDN configuration | string[] |
| NS | Name server records | DNS delegation, authoritative servers | string[] |
| SOA | Start of Authority | Zone information, DNS administration | SoaRecord |
| SRV | Service records | Service discovery, load balancing | SrvRecord[] |
| PTR | Pointer records (reverse DNS) | IP to domain mapping, security verification | string[] |
| CAA | Certificate Authority Authorization | SSL certificate validation | CaaRecord[] |
| NAPTR | Name Authority Pointer | Complex service resolution | NaptrRecord[] |
| TLSA | Transport Layer Security Authentication | Certificate pinning, security | TlsaRecord[] |
| ANY | All available records | Comprehensive domain analysis | AnyRecord[] |
Record Type Examples
// A records - IPv4 addresses
const ipv4 = await resolve4('example.com');
// Returns: ['93.184.216.34']
// MX records - Mail servers with priority
const mailServers = await resolveMx('example.com');
// Returns: [{ priority: 10, exchange: 'mail.example.com' }]
// TXT records - Text data (SPF, DKIM, etc.)
const txtRecords = await resolveTxt('example.com');
// Returns: [['v=spf1 include:_spf.example.com ~all']]
// SRV records - Service discovery
const services = await resolveSrv('_sip._tcp.example.com');
// Returns: [{ priority: 10, weight: 5, port: 5060, name: 'sip.example.com' }]🔷 TypeScript Support
YQ-DNS is built with TypeScript from the ground up, providing comprehensive type definitions, full IntelliSense support, and compile-time type checking. The library exports all necessary types and interfaces, ensuring type safety across your entire DNS resolution workflow and eliminating runtime type errors.
Complete Type Safety
import { YqDns, MxRecord, SrvRecord, ProviderName } from 'yq-dns';
// Strongly typed results with full IntelliSense
const mxRecords: MxRecord[] = await resolveMx('example.com');
const srvRecords: SrvRecord[] = await resolveSrv('_sip._tcp.example.com');
// Type-safe provider names prevent typos
const provider: ProviderName = 'google';
const addresses = await resolve4('example.com', undefined, provider);Available Type Exports
// Core types
import {
YqDns, // Main DNS class
ProviderName, // 'google' | 'cloudflare' | 'quad9' | 'native'
YqConfig, // Configuration interface
ProviderConfig, // Individual provider configuration
// DNS record types
MxRecord, // Mail exchange record
SrvRecord, // Service record
SoaRecord, // Start of Authority record
CaaRecord, // Certificate Authority Authorization
NaptrRecord, // Name Authority Pointer
TlsaRecord, // Transport Layer Security Authentication
AnyRecord, // Union of all record types
// Email validation types
EmailValidator, // Email validation class
EmailResponse, // Validation response type
EmailData, // Successful validation data
EmailError // Validation error type
} from 'yq-dns';Generic Type Support
// Generic functions with type inference
const resolveWithType = async <T>(hostname: string, type: string): Promise<T> => {
// Type-safe resolution with custom return types
return await dns.resolveAny(hostname) as T;
};
// Usage with automatic type inference
const mxRecords = await resolveWithType<MxRecord[]>('example.com', 'MX');📄 License
MIT License - see the LICENSE file for details.
Made with ❤️ by Yuniq Solutions Tech
For more information, visit our GitHub repository or check out our documentation.
