88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
import {
|
|
isPossiblePhoneNumber,
|
|
ParseError,
|
|
parsePhoneNumber,
|
|
validatePhoneNumberLength,
|
|
} from "libphonenumber-js"
|
|
import { z } from "zod"
|
|
|
|
const enum ParseErrorMessage {
|
|
INVALID_COUNTRY = "INVALID_COUNTRY",
|
|
INVALID_LENGTH = "INVALID_LENGTH",
|
|
NOT_A_NUMBER = "NOT_A_NUMBER",
|
|
TOO_LONG = "TOO_LONG",
|
|
TOO_SHORT = "TOO_SHORT",
|
|
}
|
|
|
|
export function phoneValidator(
|
|
msg = "Required field",
|
|
invalidMsg = "Invalid type"
|
|
) {
|
|
return z
|
|
.string({ invalid_type_error: invalidMsg, required_error: msg })
|
|
.min(1, { message: msg })
|
|
.superRefine((value, ctx) => {
|
|
if (value) {
|
|
try {
|
|
const phoneNumber = parsePhoneNumber(value)
|
|
if (phoneNumber) {
|
|
if (isPossiblePhoneNumber(value, phoneNumber.country)) {
|
|
return validatePhoneNumberLength(value, phoneNumber.country)
|
|
} else {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "Please enter a valid phone number",
|
|
})
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof ParseError) {
|
|
/**
|
|
* Only setup for when we need proper validation,
|
|
* should probably move to .superRefine to be able
|
|
* to return different messages depending on error.
|
|
*/
|
|
switch (error.message) {
|
|
case ParseErrorMessage.INVALID_COUNTRY:
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message:
|
|
"The country selected and country code doesn't match",
|
|
})
|
|
break
|
|
case ParseErrorMessage.INVALID_LENGTH:
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "Please enter a valid phone number",
|
|
})
|
|
break
|
|
case ParseErrorMessage.NOT_A_NUMBER:
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "Please enter a number",
|
|
})
|
|
break
|
|
case ParseErrorMessage.TOO_LONG:
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "The number you have entered is too long",
|
|
})
|
|
break
|
|
case ParseErrorMessage.TOO_SHORT:
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "The number you have entered is too short",
|
|
})
|
|
break
|
|
}
|
|
} else {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: "The number you have entered is not valid",
|
|
})
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|