Skip to content

feat: MAC address validation in v4 and mini#5440

Merged
colinhacks merged 7 commits intocolinhacks:mainfrom
ThanGerlek:mac-address-validation-v4
Nov 18, 2025
Merged

feat: MAC address validation in v4 and mini#5440
colinhacks merged 7 commits intocolinhacks:mainfrom
ThanGerlek:mac-address-validation-v4

Conversation

@ThanGerlek
Copy link
Copy Markdown
Contributor

@ThanGerlek ThanGerlek commented Nov 13, 2025

Description

This PR adds z.mac() for validating standard 48-bit MAC addresses in Zod 4 and Zod Mini. Closes #3970.

This PR is essentially a rewrite from scratch (using v4) of PR #3972, a proposed implementation for v3 that went stale (if this PR is merged I recommend it be closed). Credit to its author (@sumit6499) for most of the test cases.

Decisions

  • Only accepts standard formats, even though nonstandard ones are referenced in some places
    • Nonstandard formats have been asked for, but Zod seems stick to official formats, so I kept it as-is for functional consistency. Happy to change this.
  • Supports colons or hyphens as separators, but enforces consistency
  • Supports upper or lowercase, but enforces consistency
  • Only allows 48-bit MAC (EUI-64 can be added as its own method later if requested)

Changes

  • Add z.mac() to v4 and mini
  • Add unit tests
  • Update documentation

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 13, 2025

Walkthrough

This PR introduces MAC address validation support to Zod. The changes add a new public API method z.mac() for validating 48-bit MAC addresses in various formats (colon or dash-separated hex pairs). Implementation includes a regex pattern for validation, core schema definitions, both classic and mini schema variants, comprehensive test coverage across parsing, JSON Schema serialization, and template literals, plus documentation updates and error message localization for the new format.

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding MAC address validation support to Zod v4 and mini versions.
Linked Issues check ✅ Passed The PR fully implements the objective from issue #3970 by adding z.mac() for MAC address validation, matching the desired API and providing the requested functionality.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing MAC address validation in v4 and mini, with documentation and tests—no unrelated modifications detected.
Description check ✅ Passed The PR description clearly explains the addition of z.mac() for MAC address validation, decisions made, and changes included.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/zod/src/v4/core/schemas.ts (1)

4305-4328: Wire MAC into the string format type union

Nice job on the constructor, but the $ZodStringFormatTypes union still doesn’t list $ZodMAC, so the new schema never shows up in the exported type surface. Let’s drop it into that union right next to the other network formats.

   | $ZodIPv4
   | $ZodIPv6
   | $ZodCIDRv4
   | $ZodCIDRv6
+  | $ZodMAC
   | $ZodBase64
🧹 Nitpick comments (3)
packages/zod/src/v4/core/regexes.ts (1)

62-63: MAC regex looks solid

Enforces 6 octets, consistent separator, and consistent letter case. Anchors and backrefs are correct. Nice.

Optional: add a short comment explaining the two-branch approach and backref group numbers to prevent accidental breakage later:

 export const ipv6: RegExp =
   /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
+// MAC (48‑bit): either all‑upper or all‑lower hex pairs, with a consistent ":" or "-" separator.
+// Note: group numbering matters — upper branch uses \3, lower branch uses \6 for the separator backref.
 export const mac: RegExp =
   /^(([0-9A-F]{2}([-:])[0-9A-F]{2}(\3[0-9A-F]{2}){4})|([0-9a-f]{2}([-:])[0-9a-f]{2}(\6[0-9a-f]{2}){4}))$/;
packages/zod/src/v4/mini/tests/string.test.ts (1)

244-256: Mini mac tests cover the essentials

Valid (colon/hyphen, mixed case variants) and invalid (separator/case mix, wrong type) are well covered.

Optional: add one more negative like "001A.2B3C.4D5E" (Cisco dotted) to assert nonstandard formats are rejected, or a digits-only positive like "00:11:22:33:44:55" to ensure case-consistency logic doesn't trip on numerals.

Also applies to: 503-505

packages/zod/src/v4/core/api.ts (1)

348-363: Factory looks right; consider trimming “version” from MAC params

The _mac() factory mirrors other formats. Minor: $ZodMACParams/$ZodCheckMACParams omit "version", which isn’t applicable to MAC; you can drop it for a tighter public type.

-export type $ZodMACParams = StringFormatParams<schemas.$ZodMAC, "pattern" | "when" | "version">;
-export type $ZodCheckMACParams = CheckStringFormatParams<schemas.$ZodMAC, "pattern" | "when" | "version">;
+export type $ZodMACParams = StringFormatParams<schemas.$ZodMAC, "pattern" | "when">;
+export type $ZodCheckMACParams = CheckStringFormatParams<schemas.$ZodMAC, "pattern" | "when">;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3ec66c and 4564c90.

📒 Files selected for processing (13)
  • packages/docs/content/api.mdx (2 hunks)
  • packages/docs/content/json-schema.mdx (1 hunks)
  • packages/zod/src/v4/classic/schemas.ts (1 hunks)
  • packages/zod/src/v4/classic/tests/continuability.test.ts (1 hunks)
  • packages/zod/src/v4/classic/tests/string.test.ts (2 hunks)
  • packages/zod/src/v4/classic/tests/template-literal.test.ts (5 hunks)
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts (2 hunks)
  • packages/zod/src/v4/core/api.ts (1 hunks)
  • packages/zod/src/v4/core/regexes.ts (1 hunks)
  • packages/zod/src/v4/core/schemas.ts (1 hunks)
  • packages/zod/src/v4/locales/en.ts (1 hunks)
  • packages/zod/src/v4/mini/schemas.ts (1 hunks)
  • packages/zod/src/v4/mini/tests/string.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,jsx,ts,tsx,mjs,cjs,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Enforce line width of 120 characters via Biome formatting

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (CLAUDE.md)

Use ES5-style trailing commas in JavaScript/TypeScript code

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Allow the any type in TypeScript (noExplicitAny off)
Allow non-null assertions in TypeScript (noNonNullAssertion off)
Write TypeScript to pass strict mode with exactOptionalPropertyTypes enabled
Use NodeNext module resolution semantics for imports in TypeScript
Target ES2020 language features in TypeScript source

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
**/*.{ts,tsx,js,jsx,mjs,cjs}

📄 CodeRabbit inference engine (CLAUDE.md)

Allow parameter reassignment for performance-sensitive code (noParameterAssign off)

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
**/*.{js,mjs,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

**/*.{js,mjs,ts,tsx}: Use .js extensions in import specifiers (e.g., import { z } from "./index.js")
Don’t use require(); use ESM import statements

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
**/*.{js,mjs,cjs,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/guidelines.mdc)

Do not leave log statements (e.g., console.log, debugger) in tests or production code

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
packages/**/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/zod-project-guide.mdc)

Write source code in TypeScript (TypeScript-first codebase)

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
packages/zod/**

📄 CodeRabbit inference engine (.cursor/rules/zod-project-guide.mdc)

Make core Zod library changes in the main package at packages/zod/

Files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/core/regexes.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/locales/en.ts
  • packages/zod/src/v4/core/schemas.ts
packages/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/zod-project-guide.mdc)

Use Vitest for tests and place test cases in .test.ts files

Files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*

📄 CodeRabbit inference engine (.cursor/rules/testing-guidelines.mdc)

Place all test files under packages/zod/src/v4/classic/tests, packages/zod/src/v4/core/tests, or packages/zod/src/v3/tests

Files:

  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/testing-guidelines.mdc)

packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts: Test files must use the .test.ts extension (TypeScript), not JavaScript
Use import type for type-only imports in tests (e.g., import type { ... })
Permanent, regression, API validation, edge-case coverage, and performance benchmark tests must be in the test suite (not play.ts)
Use Vitest as the framework in tests and import from it as import { expect, test } from "vitest"
Import Zod in tests as import * as z from "zod/v4"
Write tests with clear, descriptive names and cover both success and failure cases
Keep test suites concise while maintaining adequate coverage
Do not skip tests due to type issues; fix the types instead
Use descriptive file names like string.test.ts, object.test.ts, url-validation.test.ts and group related functionality together

Files:

  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
packages/zod/src/v4/{classic,core}/tests/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/testing-workflow.mdc)

packages/zod/src/v4/{classic,core}/tests/**/*.test.ts: Use Vitest for all testing (Vitest APIs in test files)
Place tests under packages/zod/src/v4/classic/tests/ or packages/zod/src/v4/core/tests/
Name test files with the *.test.ts suffix
Use test() for individual test cases
Use describe() for test groups
Use expect() for assertions

Files:

  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
packages/zod/src/v4/core/{schemas.ts,core.ts}

📄 CodeRabbit inference engine (.cursor/rules/zod-internals.mdc)

Use the custom constructor system via core.$constructor() and initialize instances with $ZodType.init() when creating schemas

Files:

  • packages/zod/src/v4/core/schemas.ts
packages/zod/src/v4/core/schemas.ts

📄 CodeRabbit inference engine (.cursor/rules/zod-internals.mdc)

packages/zod/src/v4/core/schemas.ts: Wrapper schemas (e.g., $ZodOptional, $ZodNullable, $ZodReadonly) must pass through internal properties from their inner type using util.defineLazy for propValues, values, optin, and optout
Define computed internal properties using util.defineLazy() to avoid circular dependencies
Implement schema parse functions following the standard structure: type check, push invalid_type issue on mismatch, optionally coerce/transform, and return payload
For $ZodDiscriminatedUnion, compute and merge propValues lazily from options; ensure each option provides the discriminator key and that values are unique
Ensure readonly wrapper types (e.g., $ZodReadonly) pass through values for discriminator support in unions

Files:

  • packages/zod/src/v4/core/schemas.ts
packages/zod/src/v4/core/{schemas.ts,checks.ts}

📄 CodeRabbit inference engine (.cursor/rules/zod-internals.mdc)

When adding issues, push well-formed payload.issues entries including code, expected (when applicable), input, inst, and optional path/message/continue

Files:

  • packages/zod/src/v4/core/schemas.ts
🧠 Learnings (19)
📚 Learning: 2025-10-21T17:27:32.492Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/zod-internals.mdc:0-0
Timestamp: 2025-10-21T17:27:32.492Z
Learning: Applies to packages/zod/src/v4/core/{schemas.ts,core.ts} : Use the custom constructor system via core.$constructor() and initialize instances with $ZodType.init() when creating schemas

Applied to files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/core/api.ts
  • packages/zod/src/v4/core/schemas.ts
📚 Learning: 2025-10-21T17:27:32.492Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/zod-internals.mdc:0-0
Timestamp: 2025-10-21T17:27:32.492Z
Learning: Applies to packages/zod/src/v4/core/schemas.ts : Wrapper schemas (e.g., $ZodOptional, $ZodNullable, $ZodReadonly) must pass through internal properties from their inner type using util.defineLazy for propValues, values, optin, and optout

Applied to files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/core/schemas.ts
📚 Learning: 2025-10-21T17:27:32.492Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/zod-internals.mdc:0-0
Timestamp: 2025-10-21T17:27:32.492Z
Learning: Applies to packages/zod/src/v4/core/schemas.ts : Define computed internal properties using util.defineLazy() to avoid circular dependencies

Applied to files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/core/schemas.ts
📚 Learning: 2025-10-21T17:27:32.492Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/zod-internals.mdc:0-0
Timestamp: 2025-10-21T17:27:32.492Z
Learning: Applies to packages/zod/src/v4/core/schemas.ts : Implement schema parse functions following the standard structure: type check, push invalid_type issue on mismatch, optionally coerce/transform, and return payload

Applied to files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/classic/schemas.ts
📚 Learning: 2025-10-21T17:27:32.492Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/zod-internals.mdc:0-0
Timestamp: 2025-10-21T17:27:32.492Z
Learning: Applies to packages/zod/src/v4/core/errors.ts : Define and use canonical error types/codes as declared in errors.ts (e.g., invalid_type, TooBig/TooSmall, InvalidStringFormat, InvalidUnion, Custom)

Applied to files:

  • packages/zod/src/v4/mini/schemas.ts
  • packages/zod/src/v4/locales/en.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Use descriptive file names like string.test.ts, object.test.ts, url-validation.test.ts and group related functionality together

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Write tests with clear, descriptive names and cover both success and failure cases

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Permanent, regression, API validation, edge-case coverage, and performance benchmark tests must be in the test suite (not play.ts)

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Keep test suites concise while maintaining adequate coverage

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Import Zod in tests as `import * as z from "zod/v4"`

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
  • packages/zod/src/v4/core/schemas.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Do not skip tests due to type issues; fix the types instead

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Use import type for type-only imports in tests (e.g., `import type { ... }`)

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
📚 Learning: 2025-10-21T17:26:32.924Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-workflow.mdc:0-0
Timestamp: 2025-10-21T17:26:32.924Z
Learning: Applies to packages/zod/src/v4/{classic,core}/tests/**/*.test.ts : Name test files with the *.test.ts suffix

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:32.924Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-workflow.mdc:0-0
Timestamp: 2025-10-21T17:26:32.924Z
Learning: Applies to packages/zod/src/v4/{classic,core}/tests/**/*.test.ts : Use test() for individual test cases

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Use Vitest as the framework in tests and import from it as `import { expect, test } from "vitest"`

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:32.924Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-workflow.mdc:0-0
Timestamp: 2025-10-21T17:26:32.924Z
Learning: Applies to packages/zod/src/v4/{classic,core}/tests/**/*.test.ts : Use expect() for assertions

Applied to files:

  • packages/zod/src/v4/mini/tests/string.test.ts
  • packages/zod/src/v4/classic/tests/template-literal.test.ts
  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:28:01.210Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/zod-project-guide.mdc:0-0
Timestamp: 2025-10-21T17:28:01.210Z
Learning: Applies to packages/zod/** : Make core Zod library changes in the main package at packages/zod/

Applied to files:

  • packages/zod/src/v4/classic/schemas.ts
📚 Learning: 2025-10-21T17:26:32.924Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-workflow.mdc:0-0
Timestamp: 2025-10-21T17:26:32.924Z
Learning: Applies to packages/zod/src/v4/{classic,core}/tests/**/*.test.ts : Place tests under packages/zod/src/v4/classic/tests/ or packages/zod/src/v4/core/tests/

Applied to files:

  • packages/zod/src/v4/classic/schemas.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
  • packages/zod/src/v4/classic/tests/string.test.ts
📚 Learning: 2025-10-21T17:26:08.288Z
Learnt from: CR
Repo: colinhacks/zod PR: 0
File: .cursor/rules/testing-guidelines.mdc:0-0
Timestamp: 2025-10-21T17:26:08.288Z
Learning: Applies to packages/zod/src/{v4/classic/tests,v4/core/tests,v3/tests}/**/*.test.ts : Test files must use the .test.ts extension (TypeScript), not JavaScript

Applied to files:

  • packages/zod/src/v4/classic/tests/continuability.test.ts
  • packages/zod/src/v4/classic/tests/to-json-schema.test.ts
🧬 Code graph analysis (7)
packages/zod/src/v4/mini/schemas.ts (5)
packages/zod/src/v4/core/schemas.ts (1)
  • $ZodMACInternals (790-792)
packages/zod/src/v4/core/core.ts (2)
  • $constructor (7-10)
  • $constructor (17-77)
packages/zod/src/v4/core/regexes.ts (1)
  • mac (62-63)
packages/zod/src/v4/classic/schemas.ts (1)
  • mac (626-628)
packages/zod/src/v4/core/api.ts (1)
  • $ZodMACParams (349-349)
packages/zod/src/v4/classic/tests/template-literal.test.ts (3)
packages/zod/src/v4/mini/schemas.ts (1)
  • mac (378-380)
packages/zod/src/v4/core/regexes.ts (1)
  • mac (62-63)
packages/zod/src/v4/classic/schemas.ts (1)
  • mac (626-628)
packages/zod/src/v4/classic/schemas.ts (5)
packages/zod/src/v4/core/schemas.ts (1)
  • $ZodMACInternals (790-792)
packages/zod/src/v4/core/core.ts (2)
  • $constructor (7-10)
  • $constructor (17-77)
packages/zod/src/v4/mini/schemas.ts (1)
  • mac (378-380)
packages/zod/src/v4/core/regexes.ts (1)
  • mac (62-63)
packages/zod/src/v4/core/api.ts (1)
  • $ZodMACParams (349-349)
packages/zod/src/v4/core/regexes.ts (2)
packages/zod/src/v4/mini/schemas.ts (1)
  • mac (378-380)
packages/zod/src/v4/classic/schemas.ts (1)
  • mac (626-628)
packages/zod/src/v4/core/api.ts (2)
packages/zod/src/v4/core/schemas.ts (2)
  • $ZodMAC (794-796)
  • $ZodMAC (798-803)
packages/zod/src/v4/core/util.ts (1)
  • SchemaClass (164-166)
packages/zod/src/v4/classic/tests/string.test.ts (3)
packages/zod/src/v4/mini/schemas.ts (1)
  • mac (378-380)
packages/zod/src/v4/core/regexes.ts (1)
  • mac (62-63)
packages/zod/src/v4/classic/schemas.ts (1)
  • mac (626-628)
packages/zod/src/v4/core/schemas.ts (1)
packages/zod/src/v4/core/core.ts (2)
  • $constructor (7-10)
  • $constructor (17-77)
🔇 Additional comments (8)
packages/docs/content/json-schema.mdx (1)

84-84: Docs update LGTM

z.mac() correctly listed under pattern-based formats.

packages/zod/src/v4/classic/tests/continuability.test.ts (1)

198-219: Continuability snapshot for mac looks good

Matches existing pattern for invalid_format + custom issue; regex string is escaped consistently.

packages/zod/src/v4/classic/tests/template-literal.test.ts (1)

46-46: Template literal integration for mac is consistent

Constructor, type inference, success/failure cases, and pattern snapshot align with other string formats.

Also applies to: 141-142, 366-367, 503-505, 576-578

packages/zod/src/v4/classic/tests/to-json-schema.test.ts (1)

135-142: JSON Schema mapping for mac looks right

Produces { type: "string", format: "mac", pattern: ... } consistently. Snapshots read clean.

Also applies to: 368-376

packages/zod/src/v4/locales/en.ts (1)

63-63: Good noun mapping

Adds "MAC address" for nicer invalid_format messages.

packages/docs/content/api.mdx (1)

262-262: API docs read well

  • z.mac() listed among string formats.
  • MAC section clearly explains accepted formats and constraints with examples.

Also applies to: 519-531

packages/zod/src/v4/classic/schemas.ts (1)

617-629: MAC classic constructor is correctly wired

Init sequence mirrors other formats; no issues spotted. Please just confirm it’s re-exported from the v4 entry so tests import z.mac() cleanly.

packages/zod/src/v4/classic/tests/string.test.ts (1)

778-780: LGTM: format is exposed as "mac"

Assertion matches other string formats.

Comment thread packages/zod/src/v4/classic/tests/string.test.ts
Comment on lines +369 to +381
// ZodMiniMAC
export interface ZodMiniMAC extends _ZodMiniString<core.$ZodMACInternals> {
// _zod: core.$ZodMACInternals;
}
export const ZodMiniMAC: core.$constructor<ZodMiniMAC> = /*@__PURE__*/ core.$constructor("ZodMiniMAC", (inst, def) => {
core.$ZodMAC.init(inst, def);
ZodMiniStringFormat.init(inst, def);
});

export function mac(params?: string | core.$ZodMACParams): ZodMiniMAC {
return core._mac(ZodMiniMAC, params);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Regex backref bug will make z.mac() reject valid inputs

Wiring looks good, but core regex uses self-references (\3, \6) instead of the separator group, so valid MACs won’t match. Fix the pattern to backref the right capture.

Apply in packages/zod/src/v4/core/regexes.ts:

-export const mac: RegExp =
-  /^(([0-9A-F]{2}([-:])[0-9A-F]{2}(\3[0-9A-F]{2}){4})|([0-9a-f]{2}([-:])[0-9a-f]{2}(\6[0-9a-f]{2}){4}))$/;
+export const mac: RegExp =
+  /^(([0-9A-F]{2}([-:])[0-9A-F]{2}(\2[0-9A-F]{2}){4})|([0-9a-f]{2}([-:])[0-9a-f]{2}(\5[0-9a-f]{2}){4}))$/;

Committable suggestion skipped: line range outside the PR's diff.

@ThanGerlek
Copy link
Copy Markdown
Contributor Author

Implemented coderabbit's suggestions, except:

  • Kept "version" in case EUI-64 is ever added
  • Pretty sure coderabbit was just wrong about the regex backrefs

@colinhacks
Copy link
Copy Markdown
Owner

Love it! Make some tweaks.

  • Added a generic delimiter. Doesn't support cisco-style but I doubt anyone will ask
  • Defaults to colons-only. I think a reasonable default based on expectations, and delimiter makes it easy to support hyphen-delimited anyway
  • Dropped version from the def. Appreciate the gesture towards future-proofing but we can always add that back in if/when additional mac address formats are supported

Gonna merge this eagerly but feel free to comment if you think any of these changes are egregious and we can fix before publishing this in Zod 4.2

@colinhacks colinhacks merged commit 3d93a7d into colinhacks:main Nov 18, 2025
5 checks passed
@ThanGerlek ThanGerlek deleted the mac-address-validation-v4 branch November 18, 2025 19:12
@mootari
Copy link
Copy Markdown
Contributor

mootari commented Nov 20, 2025

@colinhacks To double-check, did you mean to include the .cursor/agent changes in your commit?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for MAC Address validation

3 participants