Skip to content

Conversation

@yslpn
Copy link
Contributor

@yslpn yslpn commented Aug 23, 2025

Add domain() validation action (ASCII domains) + docs

Closes #1277

Summary

  • Introduces domain() validation action for ASCII domain names
  • Adds API docs (action + types)

Rationale

  • Uses battle-tested regex from Zod (Docs / Github) ) instead of a custom one
/^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;

UPD: Zod regex with small updates #1284 (comment)

Decisions

  • localhost and bare intranet-like hostnames are considered invalid for domain() (by design)
  • Regex focuses on label rules and TLD; we do not enforce total domain length (max 253 chars)

Limitations

  • Total domain length is not checked
  • Unicode or IDN/Punycode is not supported (ASCII TLD required)

Discuss

We can switch to a regex that supports Punycode TLD (and total length) if desired

/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+(?:[a-z]{2,}|xn--[a-z0-9-]{2,})$/i

The advantage of this solution is that we can add toPunycode() and use it before domain() for unicode domains.

If we go with a solution that only checks simple cases, we will face the need to add a separate rfcDomain action, as it happens now with email + rfcEmail.

What do you think about this?

Copilot AI review requested due to automatic review settings August 23, 2025 12:33
@vercel
Copy link

vercel bot commented Aug 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
valibot Ready Ready Preview Comment Aug 25, 2025 7:57am

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. documentation Improvements or additions to documentation enhancement New feature or request labels Aug 23, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new domain() validation action for validating ASCII domain names in the Valibot library. The implementation focuses on providing a conservative regex-based approach to domain validation.

  • Adds core domain() action with TypeScript interfaces and comprehensive test coverage
  • Implements ASCII-only domain validation with support for Punycode IDN labels
  • Creates complete API documentation including examples and related actions

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
library/src/regex.ts Adds DOMAIN_REGEX constant for ASCII domain validation
library/src/actions/domain/domain.ts Core implementation of domain validation action with interfaces
library/src/actions/domain/domain.test.ts Comprehensive test suite covering valid/invalid domain cases
library/src/actions/domain/domain.test-d.ts TypeScript type checking tests for the domain action
library/src/actions/index.ts Exports the new domain action module
website/src/routes/api/menu.md Updates API menu to include domain action and types
website/src/routes/api/(actions)/domain/index.mdx Complete API documentation with examples and usage guidelines
website/src/routes/api/(actions)/url/index.mdx Cross-references the new domain action from URL documentation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Aug 24, 2025

Open in StackBlitz

npm i https://pkg.pr.new/valibot@1284

commit: 1674aab

@fabian-hiller
Copy link
Owner

Thank you for this PR! Do "normal" domains only support a single - but Punycode TLDs require two? Are there any other differences?

@yslpn
Copy link
Contributor Author

yslpn commented Aug 24, 2025

Do "normal" domains only support a single - but Punycode TLDs require two? Are there any other differences?

  1. Top level domains can contain numbers for punycode, but not for regular domains;
  2. Labels and TLDs start with xn--;
  3. Normal domains can support double - for label. The main thing is that it is not at the beginning or end of the label.
  4. Regular TLDs do not contain -.

The difficulty is that the specification does not have regular expressions. And in the literature, for example, https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html, fairly primitive regular expressions are presented.

Determining the correct domain is more about procedures, not about patterns. We will not be able to achieve perfect validation, but we can somehow get closer to it.

and just for information, the source of truth for all TLDs:
https://data.iana.org/TLD/tlds-alpha-by-domain.txt

@fabian-hiller
Copy link
Owner

Would your recommendation be to introduce domain for "normal" domains and add rfcDomain later on as needed like we did with email and rfcEmail?

@yslpn
Copy link
Contributor Author

yslpn commented Aug 24, 2025

Would your recommendation be to introduce domain for "normal" domains and add rfcDomain later on as needed like we did with email and rfcEmail?

I think we can go ahead with only ASCII checking, which we call "regular" or "normal" domain. Then we can add rfcDomain if someone needs it.

But before that, I think we should make the current zod regular expression a bit stricter:

  1. Add the i flag, which will make the regular expression shorter a-zA-Z => a-z
  2. Add a limit on the TLD length [a-z]{2,}$ => [a-z]{2,63}$, which is standard
  3. Limit the total string length (?=.{1,253}$), which is standard

Seems pretty safe.

The final result:

/^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i;

After that, I will add new tests and the documentation description.

UPD: Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: Add domain() validator to Valibot

2 participants