Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 1x 186x 15x 42x 19x 23x 5x 18x 42x 12x 30x 30x 1x 29x 1x 28x 42x 37x 5x 5x 5x 1x 4x 1x 3x 42x 40x 2x 42x 36x 6x 42x 210x | import type { FieldValue, NormalizedField, ValidationMessageKey } from "../schema/types";
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
function isEmpty(value: FieldValue): boolean {
return value === undefined || value === null || value === "";
}
function message(field: NormalizedField, key: ValidationMessageKey, fallback: string): string {
return field.validationMessages?.[key] ?? fallback;
}
export function validateRequired(field: NormalizedField, value: FieldValue): string | null {
if (!field.required) {
return null;
}
if (field.type === "checkbox") {
return value === true ? null : message(field, "required", `${field.label} is required.`);
}
return isEmpty(value) ? message(field, "required", `${field.label} is required.`) : null;
}
export function validateStringLength(field: NormalizedField, value: FieldValue): string | null {
if (isEmpty(value)) {
return null;
}
const valueAsString = String(value);
if (field.minLength !== undefined && valueAsString.length < field.minLength) {
return message(
field,
"minLength",
`${field.label} must be at least ${field.minLength} characters.`
);
}
if (field.maxLength !== undefined && valueAsString.length > field.maxLength) {
return message(
field,
"maxLength",
`${field.label} must be no more than ${field.maxLength} characters.`
);
}
return null;
}
export function validateNumberRange(field: NormalizedField, value: FieldValue): string | null {
if (isEmpty(value) || (field.min === undefined && field.max === undefined)) {
return null;
}
const numberValue = Number(value);
Iif (Number.isNaN(numberValue)) {
return message(field, "number", `${field.label} must be a number.`);
}
if (field.min !== undefined && numberValue < field.min) {
return message(field, "min", `${field.label} must be at least ${field.min}.`);
}
if (field.max !== undefined && numberValue > field.max) {
return message(field, "max", `${field.label} must be no more than ${field.max}.`);
}
return null;
}
export function validatePattern(field: NormalizedField, value: FieldValue): string | null {
if (isEmpty(value) || !field.pattern) {
return null;
}
return new RegExp(field.pattern).test(String(value))
? null
: message(field, "pattern", `${field.label} has an invalid format.`);
}
export function validateEmail(field: NormalizedField, value: FieldValue): string | null {
if (isEmpty(value) || field.type !== "email") {
return null;
}
return emailPattern.test(String(value))
? null
: message(field, "email", `${field.label} must be a valid email address.`);
}
export function runBuiltInValidators(field: NormalizedField, value: FieldValue): string[] {
const results = [
validateRequired(field, value),
validateStringLength(field, value),
validateNumberRange(field, value),
validatePattern(field, value),
validateEmail(field, value)
];
return results.filter((result): result is string => Boolean(result));
}
|