Skip to content

Commit

Permalink
Strict RFC4122 UUID validation and separate guid validation (#2872)
Browse files Browse the repository at this point in the history
* Add test for stricter UUID

* Add test for stricter UUID (mirror in Deno tests)

* Add test for separate guid string validator

* Update UUID to follow RFC4122 strictly

* Add guid string validator

* Change test.each to array.forEach for automatic deno build

* Add isGUID method

* Add other uuid regexes

* Update tests

---------

Co-authored-by: Colin McDonnell <[email protected]>
  • Loading branch information
jeansibelius and colinhacks authored Apr 24, 2024
1 parent 12eca8e commit 35b25b9
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 52 deletions.
1 change: 1 addition & 0 deletions deno/lib/ZodError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export type StringValidation =
| "emoji"
| "uuid"
| "nanoid"
| "guid"
| "regex"
| "cuid"
| "cuid2"
Expand Down
88 changes: 64 additions & 24 deletions deno/lib/__tests__/string.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,30 +283,6 @@ test("emoji validations", () => {
expect(() => emoji.parse("stuff😀")).toThrow();
});

test("uuid", () => {
const uuid = z.string().uuid("custom error");
uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0");
uuid.parse("d89e7b01-7598-ed11-9d7a-0022489382fd"); // new sequential id
uuid.parse("00000000-0000-0000-0000-000000000000");
uuid.parse("b3ce60f8-e8b9-40f5-1150-172ede56ff74"); // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
uuid.parse("92e76bf9-28b3-4730-cd7f-cb6bc51f8c09"); // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
const result = uuid.safeParse("9491d710-3185-4e06-bea0-6a2f275345e0X");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
});

test("bad uuid", () => {
const uuid = z.string().uuid("custom error");
uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0");
const result = uuid.safeParse("invalid uuid");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
});

test("nanoid", () => {
const nanoid = z.string().nanoid("custom error");
nanoid.parse("lfNZluvAxMkf7Q8C5H-QS");
Expand All @@ -330,6 +306,70 @@ test("bad nanoid", () => {
}
});

[
"9491d710-3185-1e06-bea0-6a2f275345e0",
"9491d710-3185-2e06-bea0-6a2f275345e0",
"9491d710-3185-3e06-bea0-6a2f275345e0",
"9491d710-3185-4e06-bea0-6a2f275345e0",
"9491d710-3185-5e06-bea0-6a2f275345e0",
"9491d710-3185-5e06-aea0-6a2f275345e0",
"9491d710-3185-5e06-8ea0-6a2f275345e0",
"9491d710-3185-5e06-9ea0-6a2f275345e0",
"00000000-0000-0000-0000-000000000000",
].forEach((goodUuid) =>
test(`uuid: ${goodUuid}`, () => {
const uuid = z.string().uuid("custom error");
const result = uuid.safeParse(goodUuid);
expect(result.success).toEqual(true);
})
);

[
"9491d710-3185-0e06-bea0-6a2f275345e0",
"9491d710-3185-5e06-0ea0-6a2f275345e0",
"d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
"invalid uuid",
"9491d710-3185-4e06-bea0-6a2f275345e0X",
"ffffffff-ffff-ffff-ffff-ffffffffffff",
].forEach((badUuid) =>
test(`bad uuid: ${badUuid}`, () => {
const uuid = z.string().uuid("custom error");
const result = uuid.safeParse(badUuid);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
})
);

[
"9491d710-3185-4e06-bea0-6a2f275345e0",
"d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
"00000000-0000-0000-0000-000000000000",
"ffffffff-ffff-ffff-ffff-ffffffffffff",
].forEach((goodGuid) =>
test(`guid: ${goodGuid}`, () => {
const guid = z.string().guid("custom error");
const result = guid.safeParse(goodGuid);
expect(result.success).toEqual(true);
})
);

["9491d710-3185-4e06-bea0-6a2f275345e0X"].forEach((badGuid) =>
test(`bad guid: ${badGuid}`, () => {
const guid = z.string().guid("custom error");
const result = guid.safeParse(badGuid);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
})
);

test("cuid", () => {
const cuid = z.string().cuid();
cuid.parse("ckopqwooh000001la8mbi2im9");
Expand Down
35 changes: 33 additions & 2 deletions deno/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ export type ZodStringCheck =
| { kind: "emoji"; message?: string }
| { kind: "uuid"; message?: string }
| { kind: "nanoid"; message?: string }
| { kind: "guid"; message?: string }
| { kind: "cuid"; message?: string }
| { kind: "includes"; value: string; position?: number; message?: string }
| { kind: "cuid2"; message?: string }
Expand Down Expand Up @@ -594,12 +595,26 @@ const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/;
const xidRegex = /^[0-9a-v]{20}$/i;
// const uuidRegex =
// /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i;
const uuidRegex =
/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
// const uuidRegex =
// /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
const nanoidRegex = /^[a-z0-9_-]{21}$/i;
const durationRegex =
/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;

const uuidRegex =
/^([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
// const uuidv1Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv2Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-2[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv3Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv4Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv5Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const guidRegex =
/^([0-9a-f]{8}-[0-9a-f]{4}\b-[0-9a-f]{4}-[0-9a-f]{4}\b-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
// from https://stackoverflow.com/a/46181/1550155
// old version: too slow, didn't support unicode
// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
Expand Down Expand Up @@ -838,6 +853,16 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
});
status.dirty();
}
} else if (check.kind === "guid") {
if (!guidRegex.test(input.data)) {
ctx = this._getOrReturnCtx(input, ctx);
addIssueToContext(ctx, {
validation: "guid",
code: ZodIssueCode.invalid_string,
message: check.message,
});
status.dirty();
}
} else if (check.kind === "cuid") {
if (!cuidRegex.test(input.data)) {
ctx = this._getOrReturnCtx(input, ctx);
Expand Down Expand Up @@ -1056,6 +1081,9 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
nanoid(message?: errorUtil.ErrMessage) {
return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) });
}
guid(message?: errorUtil.ErrMessage) {
return this._addCheck({ kind: "guid", ...errorUtil.errToObj(message) });
}
cuid(message?: errorUtil.ErrMessage) {
return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) });
}
Expand Down Expand Up @@ -1259,6 +1287,9 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
get isNANOID() {
return !!this._def.checks.find((ch) => ch.kind === "nanoid");
}
get isGUID() {
return !!this._def.checks.find((ch) => ch.kind === "guid");
}
get isCUID() {
return !!this._def.checks.find((ch) => ch.kind === "cuid");
}
Expand Down
1 change: 1 addition & 0 deletions src/ZodError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export type StringValidation =
| "emoji"
| "uuid"
| "nanoid"
| "guid"
| "regex"
| "cuid"
| "cuid2"
Expand Down
88 changes: 64 additions & 24 deletions src/__tests__/string.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,30 +282,6 @@ test("emoji validations", () => {
expect(() => emoji.parse("stuff😀")).toThrow();
});

test("uuid", () => {
const uuid = z.string().uuid("custom error");
uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0");
uuid.parse("d89e7b01-7598-ed11-9d7a-0022489382fd"); // new sequential id
uuid.parse("00000000-0000-0000-0000-000000000000");
uuid.parse("b3ce60f8-e8b9-40f5-1150-172ede56ff74"); // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
uuid.parse("92e76bf9-28b3-4730-cd7f-cb6bc51f8c09"); // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
const result = uuid.safeParse("9491d710-3185-4e06-bea0-6a2f275345e0X");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
});

test("bad uuid", () => {
const uuid = z.string().uuid("custom error");
uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0");
const result = uuid.safeParse("invalid uuid");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
});

test("nanoid", () => {
const nanoid = z.string().nanoid("custom error");
nanoid.parse("lfNZluvAxMkf7Q8C5H-QS");
Expand All @@ -329,6 +305,70 @@ test("bad nanoid", () => {
}
});

[
"9491d710-3185-1e06-bea0-6a2f275345e0",
"9491d710-3185-2e06-bea0-6a2f275345e0",
"9491d710-3185-3e06-bea0-6a2f275345e0",
"9491d710-3185-4e06-bea0-6a2f275345e0",
"9491d710-3185-5e06-bea0-6a2f275345e0",
"9491d710-3185-5e06-aea0-6a2f275345e0",
"9491d710-3185-5e06-8ea0-6a2f275345e0",
"9491d710-3185-5e06-9ea0-6a2f275345e0",
"00000000-0000-0000-0000-000000000000",
].forEach((goodUuid) =>
test(`uuid: ${goodUuid}`, () => {
const uuid = z.string().uuid("custom error");
const result = uuid.safeParse(goodUuid);
expect(result.success).toEqual(true);
})
);

[
"9491d710-3185-0e06-bea0-6a2f275345e0",
"9491d710-3185-5e06-0ea0-6a2f275345e0",
"d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
"invalid uuid",
"9491d710-3185-4e06-bea0-6a2f275345e0X",
"ffffffff-ffff-ffff-ffff-ffffffffffff",
].forEach((badUuid) =>
test(`bad uuid: ${badUuid}`, () => {
const uuid = z.string().uuid("custom error");
const result = uuid.safeParse(badUuid);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
})
);

[
"9491d710-3185-4e06-bea0-6a2f275345e0",
"d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
"00000000-0000-0000-0000-000000000000",
"ffffffff-ffff-ffff-ffff-ffffffffffff",
].forEach((goodGuid) =>
test(`guid: ${goodGuid}`, () => {
const guid = z.string().guid("custom error");
const result = guid.safeParse(goodGuid);
expect(result.success).toEqual(true);
})
);

["9491d710-3185-4e06-bea0-6a2f275345e0X"].forEach((badGuid) =>
test(`bad guid: ${badGuid}`, () => {
const guid = z.string().guid("custom error");
const result = guid.safeParse(badGuid);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("custom error");
}
})
);

test("cuid", () => {
const cuid = z.string().cuid();
cuid.parse("ckopqwooh000001la8mbi2im9");
Expand Down
35 changes: 33 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ export type ZodStringCheck =
| { kind: "emoji"; message?: string }
| { kind: "uuid"; message?: string }
| { kind: "nanoid"; message?: string }
| { kind: "guid"; message?: string }
| { kind: "cuid"; message?: string }
| { kind: "includes"; value: string; position?: number; message?: string }
| { kind: "cuid2"; message?: string }
Expand Down Expand Up @@ -594,12 +595,26 @@ const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/;
const xidRegex = /^[0-9a-v]{20}$/i;
// const uuidRegex =
// /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i;
const uuidRegex =
/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
// const uuidRegex =
// /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
const nanoidRegex = /^[a-z0-9_-]{21}$/i;
const durationRegex =
/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;

const uuidRegex =
/^([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
// const uuidv1Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv2Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-2[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv3Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv4Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
// const uuidv5Regex =
// /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const guidRegex =
/^([0-9a-f]{8}-[0-9a-f]{4}\b-[0-9a-f]{4}-[0-9a-f]{4}\b-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
// from https://stackoverflow.com/a/46181/1550155
// old version: too slow, didn't support unicode
// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
Expand Down Expand Up @@ -838,6 +853,16 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
});
status.dirty();
}
} else if (check.kind === "guid") {
if (!guidRegex.test(input.data)) {
ctx = this._getOrReturnCtx(input, ctx);
addIssueToContext(ctx, {
validation: "guid",
code: ZodIssueCode.invalid_string,
message: check.message,
});
status.dirty();
}
} else if (check.kind === "cuid") {
if (!cuidRegex.test(input.data)) {
ctx = this._getOrReturnCtx(input, ctx);
Expand Down Expand Up @@ -1056,6 +1081,9 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
nanoid(message?: errorUtil.ErrMessage) {
return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) });
}
guid(message?: errorUtil.ErrMessage) {
return this._addCheck({ kind: "guid", ...errorUtil.errToObj(message) });
}
cuid(message?: errorUtil.ErrMessage) {
return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) });
}
Expand Down Expand Up @@ -1259,6 +1287,9 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
get isNANOID() {
return !!this._def.checks.find((ch) => ch.kind === "nanoid");
}
get isGUID() {
return !!this._def.checks.find((ch) => ch.kind === "guid");
}
get isCUID() {
return !!this._def.checks.find((ch) => ch.kind === "cuid");
}
Expand Down

0 comments on commit 35b25b9

Please sign in to comment.