fix(type): keep uppercase UUIDs valid in string.uuid JSON Schema - #1670
Conversation
The string.uuid regexes relied on the i flag for uppercase hex digits. toJsonSchema only exports the regex source as `pattern`, so the flag was dropped and the exported schema rejected uppercase UUIDs that the runtime check accepts. List both cases in the character classes instead, as string.hex already does, so runtime validation is unchanged and the exported pattern matches the same strings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- UUID regexes no longer rely on the
iflag —#versionedandv1–v8inark/type/keywords/string.tsnow spell out[\dA-Fa-f]/[89ABab]explicitly, so thepatternemitted bytoJsonSchema()matches the runtime check instead of silently dropping the flag. - Regression test added —
uuid.test.tsasserts uppercase input is accepted at runtime forstring.uuidandstring.uuid.v4, and that the exported pattern compiles and matches it.
I verified the change is behavior-preserving (the explicit classes are equivalent to the previous [\da-f]/[89ab] with i), confirmed via a local probe that the pre-fix schema emitted the lowercase-only pattern while the runtime accepted uppercase, and confirmed the new test fails against the base revision and passes here. Full suite: 1752 passing.
Scoping the fix to the built-in keyword and leaving flagged user regexes (/^abc$/i) to a separate follow-up is the right call — that broader PatternNode.reduceJsonSchema gap is pre-existing and not a regression this PR introduces.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
ssalbdivad
left a comment
There was a problem hiding this comment.
Good catch on the flag getting dropped, thanks!
Bumps all publishable packages and documents the changes merged since 2.2.6: - fix `this[]` in self-referential object types (#1618, fixes #1406, @yharaskrik) - parse string.date.epoch.parse input as milliseconds (#1669, @breken-ai) - keep uppercase UUIDs valid in string.uuid JSON Schema (#1670, @breken-ai) - render nested bigints correctly in error messages (#1626, fixes #1477, @chatman-media) - release unused parse ids from the global registry (#1673, fixes #1584 for equivalent types, @isaacwasserman) - fix crashes on Hermes and Turbopack (#1674, fixes #1645 and #1643) #1590 only adds tests, so it has no changelog entry. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

The
string.uuidregexes (#versionedandv1tov8) use theiflag so that uppercase hex digits are allowed.toJsonSchema()exports only the regex source aspattern, because JSON Schema has no way to carry flags. As a result the exported schema is stricter than the runtime check and rejects valid uppercase UUIDs:string.uuidhas the same problem. Itsformat: "uuid"branch still carries the lowercase-onlypattern, so even validators that treatformat: "uuid"as case-insensitive (ajv-formats does) reject the value. Uppercase UUIDs are common in practice: SQL Serveruniqueidentifiervalues, SwiftUUID().uuidStringand Windows GUIDs are all uppercase. So an API that validates with arktype on the server and publishes the generated JSON Schema/OpenAPI to clients ends up with clients that reject payloads the server accepts.Fix: list both cases in the character classes (
[\dA-Fa-f],[89ABab]) and drop theiflag.string.hexalready does it this way. Runtime behaviour is unchanged (the same strings match), and the exportedpatternnow agrees with it.A more general follow-up could have
PatternNode.reduceJsonSchemahandle flagged regexes (for example through a fallback code), since user regexes like/^abc$/ilose their flag the same way. I kept this PR to the built-in keyword so it stays a single, behaviour-preserving fix.Test: added a case to
ark/type/__tests__/keywords/uuid.test.ts. It checks thatstring.uuidandstring.uuid.v4accept an uppercase UUID at runtime, and that the exportedpattern, compiled without flags as JSON Schema validators do, matches it too.false !== true)uuid.test.tsChecklist:
mainbranch (based on 42c17df)pnpm prCheckslocally: I ran part of it.pnpm testpasses (1752 passing),tscis clean, and prettier and eslint--max-warnings=0pass on the changed files. I did not run the benches,buildRepoortestTsVersions.I used an AI coding assistant to find and fix this, and I checked the change and the before/after test results myself.