Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146// node:dns lookup over a fixed hosts table. A browser cannot run getaddrinfo, and the// only names a guest can reach are its own: "localhost" answers ::1 then 127.0.0.1,// the order Node's verbatim lookup gets from getaddrinfo on Linux and macOS hosts// files; IP literals answer themselves; any other name is ENOTFOUND. The resolver// (DNS queries) refuses.import type { Loop } from "./loop";import { invalidArgType } from "./errors";import { isIP } from "./net";import { refused, refusedClass } from "./refuse";
interface Address { address: string; family: 4 | 6 }interface LookupOptions { family?: number | string; all?: boolean; order?: string; verbatim?: boolean; hints?: number }
const HOSTS: Record<string, Address[]> = { localhost: [{ address: "::1", family: 6 }, { address: "127.0.0.1", family: 4 }],};
const RESOLVER_WHY = "a browser cannot send DNS queries";
function parseOptions(options: unknown): LookupOptions { if (options === undefined || options === null) return {}; if (typeof options === "number") return { family: options }; if (typeof options === "object") return options as LookupOptions; throw invalidArgType("options", "of type object", options);}
function familyOf(value: number | string | undefined): 0 | 4 | 6 { if (value === "IPv4" || value === 4) return 4; if (value === "IPv6" || value === 6) return 6; return 0;}
function notFound(hostname: string): Error { return Object.assign(new Error(`getaddrinfo ENOTFOUND ${hostname}`), { errno: -3008, code: "ENOTFOUND", syscall: "getaddrinfo", hostname, });}
/** The addresses for `hostname` in result order, or null when the name is unknown. */function answer(hostname: string, opts: LookupOptions): Address[] | null { const literal = isIP(hostname); if (literal) return [{ address: hostname, family: literal as 4 | 6 }]; const known = HOSTS[hostname.toLowerCase()]; if (!known) return null; const family = familyOf(opts.family); let list = family ? known.filter((a) => a.family === family) : [...known]; const order = opts.order ?? (opts.verbatim === false ? "ipv4first" : "verbatim"); if (order === "ipv4first") list = [...list].sort((a, b) => a.family - b.family); if (order === "ipv6first") list = [...list].sort((a, b) => b.family - a.family); return list.length ? list : null;}
export function makeDns(loop: Loop) { let defaultOrder = "verbatim";
function lookup(hostname: string, options: unknown, callback?: unknown): void { if (typeof options === "function") [callback, options] = [options, undefined]; if (typeof callback !== "function") throw invalidArgType("callback", "of type function", callback); if (typeof hostname !== "string") throw invalidArgType("hostname", "of type string", hostname); const opts = { order: defaultOrder, ...parseOptions(options) }; const cb = callback as (err: Error | null, address?: string | Address[], family?: number) => void; const found = answer(hostname, opts); // An IP literal answers on the next tick, as Node's does; a name goes through // getaddrinfo and answers in the poll phase. const deliver = isIP(hostname) ? (fn: () => void) => loop.nextTick(fn) : (fn: () => void) => loop.enqueueCompletion(fn); deliver(() => { if (!found) cb(notFound(hostname)); else if (opts.all) cb(null, found.map((a) => ({ ...a }))); else cb(null, found[0]!.address, found[0]!.family); }); }
const dnsErrorCodes = { NODATA: "ENODATA", FORMERR: "EFORMERR", SERVFAIL: "ESERVFAIL", NOTFOUND: "ENOTFOUND", NOTIMP: "ENOTIMP", REFUSED: "EREFUSED", BADQUERY: "EBADQUERY", BADNAME: "EBADNAME", BADFAMILY: "EBADFAMILY", BADRESP: "EBADRESP", CONNREFUSED: "ECONNREFUSED", TIMEOUT: "ETIMEOUT", EOF: "EOF", FILE: "EFILE", NOMEM: "ENOMEM", DESTRUCTION: "EDESTRUCTION", BADSTR: "EBADSTR", BADFLAGS: "EBADFLAGS", NONAME: "ENONAME", BADHINTS: "EBADHINTS", NOTINITIALIZED: "ENOTINITIALIZED", LOADIPHLPAPI: "ELOADIPHLPAPI", ADDRGETNETWORKPARAMS: "EADDRGETNETWORKPARAMS", CANCELLED: "ECANCELLED", };
const promises = { lookup(hostname: string, options?: unknown): Promise<Address | Address[]> { return new Promise((resolve, reject) => { const opts = parseOptions(options); lookup(hostname, opts, (err: Error | null, address: string | Address[], family: 4 | 6) => { if (err) reject(err); else resolve(opts.all ? (address as Address[]) : { address: address as string, family }); }); }); }, getDefaultResultOrder: () => defaultOrder, setDefaultResultOrder: (order: string) => { defaultOrder = order; }, ...dnsErrorCodes, resolve: refused("dns", "promises.resolve", RESOLVER_WHY), resolve4: refused("dns", "promises.resolve4", RESOLVER_WHY), resolve6: refused("dns", "promises.resolve6", RESOLVER_WHY), reverse: refused("dns", "promises.reverse", RESOLVER_WHY), resolveAny: refused("dns", "promises.resolveAny", RESOLVER_WHY), resolveCaa: refused("dns", "promises.resolveCaa", RESOLVER_WHY), resolveCname: refused("dns", "promises.resolveCname", RESOLVER_WHY), resolveMx: refused("dns", "promises.resolveMx", RESOLVER_WHY), resolveNaptr: refused("dns", "promises.resolveNaptr", RESOLVER_WHY), resolveNs: refused("dns", "promises.resolveNs", RESOLVER_WHY), resolvePtr: refused("dns", "promises.resolvePtr", RESOLVER_WHY), resolveSoa: refused("dns", "promises.resolveSoa", RESOLVER_WHY), resolveSrv: refused("dns", "promises.resolveSrv", RESOLVER_WHY), resolveTlsa: refused("dns", "promises.resolveTlsa", RESOLVER_WHY), resolveTxt: refused("dns", "promises.resolveTxt", RESOLVER_WHY), lookupService: refused("dns", "promises.lookupService", RESOLVER_WHY), getServers: refused("dns", "promises.getServers", RESOLVER_WHY), setServers: refused("dns", "promises.setServers", RESOLVER_WHY), Resolver: refusedClass("dns", "Resolver", RESOLVER_WHY), }; Object.defineProperty(lookup, Symbol.for("nodejs.util.promisify.custom"), { value: promises.lookup, enumerable: false });
return { lookup, promises, getDefaultResultOrder: () => defaultOrder, setDefaultResultOrder: (order: string) => { defaultOrder = order; }, ADDRCONFIG: 1024, V4MAPPED: 2048, ALL: 256, ...dnsErrorCodes, resolve: refused("dns", "resolve", RESOLVER_WHY), resolve4: refused("dns", "resolve4", RESOLVER_WHY), resolve6: refused("dns", "resolve6", RESOLVER_WHY), reverse: refused("dns", "reverse", RESOLVER_WHY), lookupService: refused("dns", "lookupService", RESOLVER_WHY), resolveAny: refused("dns", "resolveAny", RESOLVER_WHY), resolveCaa: refused("dns", "resolveCaa", RESOLVER_WHY), resolveCname: refused("dns", "resolveCname", RESOLVER_WHY), resolveMx: refused("dns", "resolveMx", RESOLVER_WHY), resolveNaptr: refused("dns", "resolveNaptr", RESOLVER_WHY), resolveNs: refused("dns", "resolveNs", RESOLVER_WHY), resolvePtr: refused("dns", "resolvePtr", RESOLVER_WHY), resolveSoa: refused("dns", "resolveSoa", RESOLVER_WHY), resolveSrv: refused("dns", "resolveSrv", RESOLVER_WHY), resolveTlsa: refused("dns", "resolveTlsa", RESOLVER_WHY), resolveTxt: refused("dns", "resolveTxt", RESOLVER_WHY), getServers: refused("dns", "getServers", RESOLVER_WHY), setServers: refused("dns", "setServers", RESOLVER_WHY), Resolver: refusedClass("dns", "Resolver", RESOLVER_WHY), };}