Zod adapter
@xndrjs/domain-zod integrates Zod 4 with @xndrjs/domain.
It provides:
zodToValidator(schema)to convert a Zod schema into a domain validatorzodFromKit(kit)to embed domain kits inside Zod schemas- full re-export of
@xndrjs/domainfor single-entry imports
Install
Section titled “Install”pnpm add @xndrjs/domain-zod zodMinimal example
Section titled “Minimal example”import { domain, zodToValidator } from "@xndrjs/domain-zod";import { z } from "zod";
const Email = domain.primitive( "Email", zodToValidator(z.email().transform((value) => value.toLowerCase())));
const email = Email.create("ADA@EXAMPLE.COM");// ada@example.comZod handles parsing and transformation. The domain primitive materializes the trusted value.
zodToValidator
Section titled “zodToValidator”const userValidator = zodToValidator( z.object({ id: z.string(), age: z.number().int().nonnegative(), }));
const User = domain.shape("User", userValidator);Failure mapping:
engine: "zod"- one domain issue per Zod issue
- raw issue payload available in metadata
zodFromKit
Section titled “zodFromKit”zodFromKit(kit) turns a primitive or shape kit into a Zod field. Validation and transforms run only through the kit’s validator (typically from zodToValidator on the kit); the parent schema does not add a second parsing path for that field.
const Invite = domain.shape( "Invite", zodToValidator( z.object({ recipient: zodFromKit(Email), message: z.string().min(1), }) ));Reusing shapes in parent schemas
Section titled “Reusing shapes in parent schemas”const Address = domain.shape( "Address", zodToValidator( z.object({ city: z.string().min(1), country: z.string().length(2), }) ));
const User = domain.shape( "User", zodToValidator( z.object({ id: z.string(), address: zodFromKit(Address), }) ));
const user = User.create({ id: "user_1", address: { city: "Rome", country: "IT" },});This avoids duplicating nested domain semantics in parent schemas.