@multiformats/dns
Version:
Resolve DNS queries with browser fallback
78 lines (64 loc) • 1.96 kB
text/typescript
import { Resolver } from 'dns/promises'
import { RecordType } from '../index.js'
import { getTypes } from '../utils/get-types.js'
import { toDNSResponse } from '../utils/to-dns-response.js'
import type { DNSResolver } from './index.js'
import type { Answer } from '../index.js'
const nodeResolver: DNSResolver = async (fqdn, options = {}) => {
const resolver = new Resolver()
const listener = (): void => {
resolver.cancel()
}
const types = getTypes(options.types)
try {
options.signal?.addEventListener('abort', listener)
const answers = await Promise.all(types.map(async type => {
if (type === RecordType.A) {
return mapToAnswers(fqdn, type, await resolver.resolve4(fqdn))
}
if (type === RecordType.CNAME) {
return mapToAnswers(fqdn, type, await resolver.resolveCname(fqdn))
}
if (type === RecordType.TXT) {
return mapToAnswers(fqdn, type, await resolver.resolveTxt(fqdn))
}
if (type === RecordType.AAAA) {
return mapToAnswers(fqdn, type, await resolver.resolve6(fqdn))
}
throw new TypeError('Unsupported DNS record type')
}))
return toDNSResponse({
Question: types.map(type => ({
name: fqdn,
type
})),
Answer: answers.flat()
})
} finally {
options.signal?.removeEventListener('abort', listener)
}
}
export function defaultResolver (): DNSResolver[] {
return [
nodeResolver
]
}
function mapToAnswer (name: string, type: RecordType, data: string): Omit<Answer, 'TTL'> {
return {
name,
type,
data
}
}
function mapToAnswers (name: string, type: RecordType, data: string | string[] | string[][]): Array<Omit<Answer, 'TTL'>> {
if (!Array.isArray(data)) {
data = [data]
}
return data.map(data => {
if (Array.isArray(data)) {
return data.map(data => mapToAnswer(name, type, data))
}
return mapToAnswer(name, type, data)
})
.flat()
}