API reference › @evolu/common › Type › Hostname

const Hostname: brand(
  "Hostname",
  String,
  (value: string) =>
    value.length <= 253 &&
    /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/u.test(
      value,
    ) &&
    !/(?:^|\.)(?:\d+|0x[0-9a-f]*)$/u.test(value)
      ? ok()
      : err<HostnameError>({ type: "Hostname", value }),
  formatHostnameError,
);

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"));