PolyVal is a multilingual and highly customizable validation library. It uses Zod as a backend while providing developers with a simplified API.
- Simplified API: Use without needing complex type definitions or knowledge of validation rules
- Multilingual Support: Default support for
en(English) andtr(Turkish) - Fully Customizable Error Messages: Customize error messages by field, rule type, or globally
- Custom Validation Rules: Easily define your own validation rules
- TypeScript Support: Full TypeScript support with type safety
npm install polyvalimport { validate } from 'polyval';
// Simple schema definition
const userSchema = {
username: {
type: 'string',
required: true,
min: 3,
max: 20
},
email: {
type: 'string',
required: true,
email: true
},
age: {
type: 'number',
min: 18
}
};
// Data to validate
const userData = {
username: 'jo',
email: 'invalid-email',
age: 16
};
// Validation (using Turkish language)
const errors = validate(userSchema, userData, { lang: 'tr' });
console.log(errors);
// [
// "Username: En az 3 karakter uzunluğunda olmalıdır",
// "Email: Geçersiz e-posta adresi",
// "Age: En az 18 olmalıdır"
// ]PolyVal schemas are defined using simple JavaScript objects. Each field uses a configuration object:
const schema = {
fieldName: {
type: 'string' | 'number' | 'boolean' | 'date', // Field type (required)
required: boolean, // Is field required? (default: false)
// Other validation rules...
}
};{
type: 'string',
required: boolean, // Is required?
min: number, // Minimum length
max: number, // Maximum length
length: number, // Exact length
email: boolean, // Email format
url: boolean, // URL format
uuid: boolean, // UUID format
cuid: boolean, // CUID format
datetime: boolean, // ISO 8601 datetime format
ip: 'v4' | 'v6', // IP address format
regex: string, // Regex pattern (as string)
startsWith: string, // Must start with this value
endsWith: string, // Must end with this value
numeric: boolean // Only numeric characters
}{
type: 'number',
required: boolean, // Is required?
min: number, // Minimum value
max: number // Maximum value
}{
type: 'date',
required: boolean, // Is required?
min: number, // Minimum date (timestamp)
max: number // Maximum date (timestamp)
}{
type: 'boolean',
required: boolean, // Is required?
equals: boolean // Expected to be a specific value (true/false)?
}To validate a field in relation to another field:
{
password: {
type: 'string',
required: true,
min: 8
},
confirmPassword: {
type: 'string',
required: true,
equals: 'password' // Must match the 'password' field
},
oldPassword: {
type: 'string',
required: true,
notEquals: 'password' // Must not match the 'password' field
}
}To define your own validation logic:
{
username: {
type: 'string',
required: true,
customValidators: [
{
validator: (value, data) => {
// Custom validation logic
if (value.toLowerCase() === 'admin') {
return 'This username is not available'; // Return error message
}
return undefined; // Return undefined for successful validation
},
messageKey: 'noAdminUsername' // Key to use for custom messages
}
]
}
}PolyVal allows you to fully customize error messages:
const errors = validate(schema, data, {
lang: 'en',
customMessages: {
// 1. General error messages
required: 'This field cannot be empty',
invalid_type: 'Invalid value type',
// 2. Type-based error messages
string: {
min: (min) => `Please enter at least ${min} characters`,
email: 'Please enter a valid email address'
},
number: {
min: (min) => `Value must be at least ${min}`
},
// 3. Custom comparison rule messages
equals: (field) => `This field must match the ${field} field`,
// 4. Field-based custom messages (highest priority)
fields: {
username: {
min: (min) => `Username must be at least ${min} characters`,
required: 'Username is required',
// Message for custom validation rule
noAdminUsername: 'Admin username is reserved'
}
},
// 5. Global custom validator messages
custom: {
noAdminUsername: 'Admin username cannot be used'
}
}
});Error messages are determined according to the following priority order (from highest to lowest):
- Field-based custom validator messages (
customMessages.fields['fieldName']['customMessageKey']) - Other field-based custom messages (
customMessages.fields['fieldName']['min']) - Global custom validator messages (
customMessages.custom['messageKey']) - General rule-based custom messages (
customMessages.string.email,customMessages.number.min) - General error type messages (
customMessages.required,customMessages.invalid_type) - Default messages in the selected language
import { validate } from 'polyval';
// User registration schema
const userRegistrationSchema = {
username: {
type: 'string',
required: true,
min: 3,
max: 20,
regex: '^[a-zA-Z0-9]+$', // Only alphanumeric characters
customValidators: [{
validator: (value) => value.toLowerCase() !== 'admin' ? undefined : 'Admin username is not available',
messageKey: 'noAdminUsername'
}]
},
email: {
type: 'string',
required: true,
email: true
},
age: {
type: 'number',
min: 18,
required: false
},
password: {
type: 'string',
required: true,
min: 8,
regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]+$' // Strong password
},
confirmPassword: {
type: 'string',
required: true,
equals: 'password', // Must match the 'password' field
customValidators: [{
validator: (value, data) => value !== data.password + '123' ? undefined : 'You used a predictable password',
messageKey: 'predictablePassword'
}]
},
acceptTerms: {
type: 'boolean',
required: true,
equals: true // User must accept terms
}
};
// Invalid data
const userData = {
username: "al",
email: "invalid-email",
password: "123",
confirmPassword: "456",
acceptTerms: false
};
// Validate with Turkish error messages
const errorsTR = validate(userRegistrationSchema, userData, { lang: 'tr' });
console.log(errorsTR);
// Validate with English and customized messages
const errorsEN = validate(userRegistrationSchema, userData, {
lang: 'en',
customMessages: {
string: {
min: (min) => `Please ensure this field has at least ${min} characters.`,
email: "That doesn't look like a valid email address."
},
fields: {
username: {
noAdminUsername: "Sorry, 'admin' is a reserved username."
},
confirmPassword: {
equals: "Passwords must match exactly."
}
}
}
});
console.log(errorsEN);git clone https://github.com/yourusername/polyval.git
cd polyval
npm installnpm testnpm run buildThere is an example project in the example directory that demonstrates how to use the library. To explore and run this example:
- Install and build the main PolyVal project:
npm install
npm run build- Navigate to the example project and run it:
cd example
npm install
npm run devThis example demonstrates user registration validation, multilingual error messages, and how to use customized messages.
MIT