diff --git a/ark/type/__tests__/keywords/uuid.test.ts b/ark/type/__tests__/keywords/uuid.test.ts index 3bd966dd5..0c0ec9864 100644 --- a/ark/type/__tests__/keywords/uuid.test.ts +++ b/ark/type/__tests__/keywords/uuid.test.ts @@ -25,6 +25,23 @@ contextualize(() => { ) }) + it("JSON Schema pattern accepts uppercase like the runtime check", () => { + const upper = validUuidV4.toUpperCase() + + const Uuid = type("string.uuid") + attest(Uuid(upper)).equals(upper) + const uuidSchema = Uuid.toJsonSchema() as { + anyOf: { pattern?: string }[] + } + const versionedPattern = uuidSchema.anyOf[0].pattern! + attest(new RegExp(versionedPattern, "u").test(upper)).equals(true) + + const Uuidv4 = type("string.uuid.v4") + attest(Uuidv4(upper)).equals(upper) + const v4Pattern = (Uuidv4.toJsonSchema() as { pattern: string }).pattern + attest(new RegExp(v4Pattern, "u").test(upper)).equals(true) + }) + it("rejects partial matches", () => { const Uuid = type("string.uuid") attest(Uuid("dbb1e8e0-40fc-4c14-87eb-61b25d166a1b extra").toString()).snap( diff --git a/ark/type/keywords/string.ts b/ark/type/keywords/string.ts index 0779d70a5..2b76509c3 100644 --- a/ark/type/keywords/string.ts +++ b/ark/type/keywords/string.ts @@ -841,37 +841,37 @@ export const uuid = Scope.module( "#nil": "'00000000-0000-0000-0000-000000000000'", "#max": "'ffffffff-ffff-ffff-ffff-ffffffffffff'", "#versioned": - /^[\da-f]{8}-[\da-f]{4}-[1-8][\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-[1-8][\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, v1: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-1[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-1[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv1" ), v2: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-2[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-2[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv2" ), v3: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-3[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-3[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv3" ), v4: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-4[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-4[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv4" ), v5: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-5[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-5[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv5" ), v6: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-6[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-6[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv6" ), v7: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-7[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-7[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv7" ), v8: regexStringNode( - /^[\da-f]{8}-[\da-f]{4}-8[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i, + /^[\dA-Fa-f]{8}-[\dA-Fa-f]{4}-8[\dA-Fa-f]{3}-[89ABab][\dA-Fa-f]{3}-[\dA-Fa-f]{12}$/, "a UUIDv8" ) },