API reference › @evolu/common › Type › Hostname

type Hostname = string & Brand<"Hostname">;

Defined in: packages/common/src/Type.ts:9238

Internet host name in lowercase ASCII, as defined by RFC 1123 section 2.1.

Hostname accepts at most 253 characters of dot-separated labels. Each label has 1 to 63 lowercase ASCII letters, digits, and hyphens and does not start or end with a hyphen. A single label, such as localhost, is a Hostname. Underscores are rejected, so DNS names such as _dmarc.example.com are not host names.

The last label must not be a number, such as 123 or 0x1f, because the WHATWG URL Standard parses a host ending in a number as an IPv4 address. No Hostname is an Ipv4Address, so a URL never parses a Hostname as an IPv4 address.

Hostname does not normalize. DNS compares names case-insensitively, so Hostname requires lowercase so that equal names are equal strings, and it rejects the trailing dot of a fully qualified name. Lowercase text from other sources and remove a trailing dot before validating it. Internationalized names must use their ASCII (xn--) labels; convert Unicode labels with an IDNA library first. Hostname does not verify the Punycode of xn-- labels, so URL parsers that verify it, such as Firefox's, reject a label such as xn--a that Hostname accepts.

Hostname does not require a dot; compose regex to require one.

Example

import {
  assertEqual,
  assertErr,
  assertOk,
  Hostname,
  regex,
} from "@evolu/common";

assertOk(Hostname.fromUnknown("example.com"), "example.com");
assertOk(Hostname.fromUnknown("localhost"), "localhost");
assertErr(Hostname.fromUnknown("1.2.3.4"));

const invalid = Hostname.fromUnknown("Example.com.");
assertErr(invalid);
assertEqual(invalid.error, { type: "Hostname", value: "Example.com." });

const DomainName = regex("DomainName", /\./u)(Hostname);
assertOk(DomainName.fromUnknown("example.com"), "example.com");
assertErr(DomainName.fromUnknown("localhost"));