oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
73.17k stars 2.68k forks source link

[RFC] `Bun.dns` #2069

Open colinhacks opened 1 year ago

colinhacks commented 1 year ago

A proposal for a Bun-native DNS API (Bun.dns)

Comparison to node:dns

Bun node:dns equivalent
Bun.dns.Resolver dns.Resolver No changes
Bun.dns.getServers dns.getServers No changes
Bun.dns.setServers dns.setServers No changes
Bun.dns.lookupService dns.lookupService No changes
Bun.dns.reverse dns.reverse No changes
Bun.dns.lookup dns.lookup
Bun.dns.resolve dns.resolve
Bun.dns.a dns.resolve4
Bun.dns.aaaa dns.resolve6
Bun.dns.cname dns.resolveCname
Bun.dns.caa dns.resolveCaa
Bun.dns.mx dns.resolveMx
Bun.dns.naptr dns.resolveNaptr
Bun.dns.ns dns.resolveNs
Bun.dns.ptr dns.resolvePtr
Bun.dns.soa dns.resolveSoa
Bun.dns.srv dns.resolveSrv
Bun.dns.txt dns.resolveTxt
Bun.dns.any dns.resolveAny

Spec

interface Bun {
  dns: BunDNS;
}

type RecordType =
  | 'a'
  | 'aaaa'
  | 'caa'
  | 'cname'
  | 'mx'
  | 'naptr'
  | 'ns'
  | 'ptr'
  | 'soa'
  | 'srv'
  | 'txt'
  | 'any';

interface BunDNS {
  lookup(hostname: string, {
    type?: 'a' | 'aaaa', // resolve both A and AAAA if not specified
  }): Promise<string>;

  // select multiple record types
  resolve<T extends {[k in RRType]: true} = {a: true, aaaa: true}>(hostname: string, params?: {
    types: T
  }): Promise<TRecord[]>; // compute based on T

  a(hostname: string): Promise<ARecord[]>;
  aaaa(hostname: string): Promise<AaaaRecord[]>;
  cname(hostname: string): Promise<CnameRecord[]>;
  caa(hostname: string): Promise<CaaRecord[]>;
  mx(hostname: string): Promise<MxRecord[]>;
  naptr(hostname: string): Promise<NaptrRecord[]>;
  ns(hostname: string): Promise<NsRecord[]>;
  ptr(hostname: string): Promise<PtrRecord[]>;
  soa(hostname: string): Promise<SoaRecord[]>;
  srv(hostname: string): Promise<SrvRecord[]>;
  txt(hostname: string): Promise<TxtRecord[]>;
  any(hostname: string): Promise<AnyRecord[]>;
}

interface ARecord {
  type: 'A';
  address: string;
  ttl: number;
}
interface AaaaRecord {
  type: 'AAAA';
  address: string;
  ttl: number;
}
interface CaaRecord {
  type: 'CAA';
  critial: number;
  issue?: string | undefined;
  issuewild?: string | undefined;
  iodef?: string | undefined;
  contactemail?: string | undefined;
  contactphone?: string | undefined;
}
interface MxRecord {
  type: 'MX';
  priority: number;
  exchange: string;
}
interface NaptrRecord {
  type: 'NAPTR';
  flags: string;
  service: string;
  regexp: string;
  replacement: string;
  order: number;
  preference: number;
}

interface SoaRecord {
  type: 'SOA';
  nsname: string;
  hostmaster: string;
  serial: number;
  refresh: number;
  retry: number;
  expire: number;
  minttl: number;
}

interface SrvRecord {
  type: 'SRV';
  priority: number;
  weight: number;
  port: number;
  name: string;
}
interface TxtRecord {
  type: 'TXT';
  entries: string[];
}
interface NsRecord {
  type: 'NS';
  value: string;
}
interface PtrRecord {
  type: 'PTR';
  value: string;
}
interface CnameRecord {
  type: 'CNAME';
  value: string;
}

type AnyRecord =
  | ARecord
  | AaaaRecord
  | CaaRecord
  | MxRecord
  | NaptrRecord
  | SoaRecord
  | SrvRecord
  | TxtRecord
  | NsRecord
  | PtrRecord
  | CnameRecord;
n-johnson commented 1 year ago

(Not sure what feedback is being solicited, if any, but the post is titled RFC 😄 For context, I've written a lot of code with node's dns module, and built a custom dns client in node with the native dgram module because of limitations with the native node dns module)

If the goal is node.js parity, most of these probably aren't on the table, but if extending the ecosystem, these are my thoughts.