import { getOptionValue } from "../options.ts";import { emitWarning } from "../../process.ts";import { AI_ADDRCONFIG, AI_ALL, AI_V4MAPPED,} from "../../internal_binding/ares.ts";import { ChannelWrap, strerror } from "../../internal_binding/cares_wrap.ts";import { ERR_DNS_SET_SERVERS_FAILED, ERR_INVALID_ARG_VALUE, ERR_INVALID_IP_ADDRESS,} from "../errors.ts";import type { ErrnoException } from "../errors.ts";import { validateArray, validateInt32, validateOneOf, validateString,} from "../validators.mjs";import { isIP } from "../net.ts";
export interface LookupOptions { family?: number | undefined; hints?: number | undefined; all?: boolean | undefined; verbatim?: boolean | undefined;}
export interface LookupOneOptions extends LookupOptions { all?: false | undefined;}
export interface LookupAllOptions extends LookupOptions { all: true;}
export interface LookupAddress { address: string | null; family: number;}
export function isLookupOptions( options: unknown,): options is LookupOptions | undefined { return typeof options === "object" || typeof options === "undefined";}
export function isLookupCallback( options: unknown,): options is (...args: unknown[]) => void { return typeof options === "function";}
export function isFamily(options: unknown): options is number { return typeof options === "number";}
export interface ResolveOptions { ttl?: boolean;}
export interface ResolveWithTtlOptions extends ResolveOptions { ttl: true;}
export interface RecordWithTtl { address: string; ttl: number;}
export interface AnyARecord extends RecordWithTtl { type: "A";}
export interface AnyAaaaRecord extends RecordWithTtl { type: "AAAA";}
export interface CaaRecord { critial: number; issue?: string | undefined; issuewild?: string | undefined; iodef?: string | undefined; contactemail?: string | undefined; contactphone?: string | undefined;}
export interface MxRecord { priority: number; exchange: string;}
export interface AnyMxRecord extends MxRecord { type: "MX";}
export interface NaptrRecord { flags: string; service: string; regexp: string; replacement: string; order: number; preference: number;}
export interface AnyNaptrRecord extends NaptrRecord { type: "NAPTR";}
export interface SoaRecord { nsname: string; hostmaster: string; serial: number; refresh: number; retry: number; expire: number; minttl: number;}
export interface AnySoaRecord extends SoaRecord { type: "SOA";}
export interface SrvRecord { priority: number; weight: number; port: number; name: string;}
export interface AnySrvRecord extends SrvRecord { type: "SRV";}
export interface AnyTxtRecord { type: "TXT"; entries: string[];}
export interface AnyNsRecord { type: "NS"; value: string;}
export interface AnyPtrRecord { type: "PTR"; value: string;}
export interface AnyCnameRecord { type: "CNAME"; value: string;}
export type AnyRecord = | AnyARecord | AnyAaaaRecord | AnyCnameRecord | AnyMxRecord | AnyNaptrRecord | AnyNsRecord | AnyPtrRecord | AnySoaRecord | AnySrvRecord | AnyTxtRecord;
export type Records = | string[] | AnyRecord[] | MxRecord[] | NaptrRecord[] | SoaRecord | SrvRecord[] | string[];
export type ResolveCallback = ( err: ErrnoException | null, addresses: Records,) => void;
export function isResolveCallback( callback: unknown,): callback is ResolveCallback { return typeof callback === "function";}
const IANA_DNS_PORT = 53;const IPv6RE = /^\[([^[\]]*)\]/;const addrSplitRE = /(^.+?)(?::(\d+))?$/;
export function validateTimeout(options?: { timeout?: number }) { const { timeout = -1 } = { ...options }; validateInt32(timeout, "options.timeout", -1, 2 ** 31 - 1); return timeout;}
export function validateTries(options?: { tries?: number }) { const { tries = 4 } = { ...options }; validateInt32(tries, "options.tries", 1, 2 ** 31 - 1); return tries;}
export interface ResolverOptions { timeout?: number | undefined; tries?: number;}
export class Resolver { _handle!: ChannelWrap;
constructor(options?: ResolverOptions) { const timeout = validateTimeout(options); const tries = validateTries(options); this._handle = new ChannelWrap(timeout, tries); }
cancel() { this._handle.cancel(); }
getServers(): string[] { return this._handle.getServers().map((val: [string, number]) => { if (!val[1] || val[1] === IANA_DNS_PORT) { return val[0]; }
const host = isIP(val[0]) === 6 ? `[${val[0]}]` : val[0]; return `${host}:${val[1]}`; }); }
setServers(servers: ReadonlyArray<string>) { validateArray(servers, "servers");
const orig = this._handle.getServers(); const newSet: [number, string, number][] = [];
servers.forEach((serv, index) => { validateString(serv, `servers[${index}]`); let ipVersion = isIP(serv);
if (ipVersion !== 0) { return newSet.push([ipVersion, serv, IANA_DNS_PORT]); }
const match = serv.match(IPv6RE);
if (match) { ipVersion = isIP(match[1]);
if (ipVersion !== 0) { const port = Number.parseInt(serv.replace(addrSplitRE, "$2")) || IANA_DNS_PORT;
return newSet.push([ipVersion, match[1], port]); } }
const addrSplitMatch = serv.match(addrSplitRE);
if (addrSplitMatch) { const hostIP = addrSplitMatch[1]; const port = addrSplitMatch[2] || `${IANA_DNS_PORT}`;
ipVersion = isIP(hostIP);
if (ipVersion !== 0) { return newSet.push([ipVersion, hostIP, Number.parseInt(port)]); } }
throw new ERR_INVALID_IP_ADDRESS(serv); });
const errorNumber = this._handle.setServers(newSet);
if (errorNumber !== 0) { this._handle.setServers(orig.join(",")); const err = strerror(errorNumber);
throw new ERR_DNS_SET_SERVERS_FAILED(err, servers.toString()); } }
setLocalAddress(ipv4: string, ipv6?: string) { validateString(ipv4, "ipv4");
if (ipv6 !== undefined) { validateString(ipv6, "ipv6"); }
this._handle.setLocalAddress(ipv4, ipv6); }}
let defaultResolver = new Resolver();
export function getDefaultResolver(): Resolver { return defaultResolver;}
export function setDefaultResolver<T extends Resolver>(resolver: T) { defaultResolver = resolver;}
export function validateHints(hints: number) { if ((hints & ~(AI_ADDRCONFIG | AI_ALL | AI_V4MAPPED)) !== 0) { throw new ERR_INVALID_ARG_VALUE("hints", hints, "is invalid"); }}
let invalidHostnameWarningEmitted = false;
export function emitInvalidHostnameWarning(hostname: string) { if (invalidHostnameWarningEmitted) { return; }
invalidHostnameWarningEmitted = true;
emitWarning( `The provided hostname "${hostname}" is not a valid ` + "hostname, and is supported in the dns module solely for compatibility.", "DeprecationWarning", "DEP0118", );}
let dnsOrder = getOptionValue("--dns-result-order") || "ipv4first";
export function getDefaultVerbatim() { switch (dnsOrder) { case "verbatim": { return true; } case "ipv4first": { return false; } default: { return false; } }}
export function setDefaultResultOrder(order: "ipv4first" | "verbatim") { validateOneOf(order, "dnsOrder", ["verbatim", "ipv4first"]); dnsOrder = order;}
export function defaultResolverSetServers(servers: string[]) { const resolver = new Resolver();
resolver.setServers(servers); setDefaultResolver(resolver);}