Package Exports
- @teonord/validator
Readme
@teonord/validator
Advanced validation library with multiple API styles including JSON templates, inline rules, builder pattern, and functional composition. Features 50+ built-in validators, dot notation for nested objects, field reference resolution, and internationalization support. Zero dependencies, fully synchronous, and designed for maximum developer experience with extensible custom rule system.
Features
- 🎯 Multiple Validation APIs: JSON templates, inline rules, builder pattern, functional composition
- 🏷️ TypeScript First: Full type safety and intelligent autocomplete
- 🌍 Internationalization: Multi-language error messages
- 🔧 Extensible: Custom rules and validators
- 🧪 Comprehensive Rule Set: 50+ built-in validation rules
- 🚀 Lightweight: Zero dependencies, tree-shakable
📚 Table of Contents
- Installation
- Quick Start
- JSON Template Validation
- Validation APIs
- Rule Reference
- Error Handling
- Internationalization
- Custom Rules
- API Reference
Installation
npm install @teonord/validatorExamples
Quick Start
import { Validator } from '@teonord/validator';
const data = {
name: 'John Doe',
email: 'john@example.com',
age: 25
};
const validator = new Validator(data);
const result = validator.validateRules({
name: [{ rule: 'required' }, { rule: 'minLength', value: 2 }],
email: [{ rule: 'required' }, { rule: 'email' }],
age: [{ rule: 'required' }, { rule: 'numeric' }, { rule: 'min', value: 18 }]
});
console.log(result.isValid); // true
console.log(result.errors); // []JSON Template Validation
import { Validator } from '@teonord/validator';
const data = {
username: 'john_doe',
};
const validator = new Validator(data);
const template = [
{
name: 'username',
validation: [
{
rule: 'required',
message: {
en: 'Username is required',
fr: 'Nom d\'utilisateur est requis'
}
},
{
rule: 'minLength',
value: 3,
message: {
en: 'Username must be at least 3 characters',
fr: 'Le nom d\'utilisateur doit contenir au moins 3 caractères'
}
}
]
}
];
const result = validator.validateTemplate(template);Validation APIs
JSON Template API
Structured validation with field definitions and custom messages:
import { Validator } from '@teonord/validator';
const data = {
email: 'john@example.com',
password: 'pass123',
};
const validator = new Validator(data);
const template = [
{
name: 'email',
validation: [
{
rule: 'required',
message: { en: 'Email is required', es: 'El email es requerido' }
},
{
rule: 'email',
message: { en: 'Invalid email format', es: 'Formato de email inválido' }
}
]
},
{
name: 'password',
validation: [
{
rule: 'required',
message: { en: 'Password is required', es: 'La contraseña es requerida' }
},
{
rule: 'minLength',
value: 8,
message: { en: 'Password must be 8+ characters', es: 'La contraseña debe tener 8+ caracteres' }
}
]
}
];
const result = validator.validateTemplate(template);Inline Rules API
import { Validator, parseInlineRules } from '@teonord/validator';
const data = {
username: 'john',
email: 'john@example.com',
password: 'pass123',
};
const validator = new Validator(data);
const rules = {
username: parseInlineRules('required|minLength:3|maxLength:20|alphaDash'),
email: parseInlineRules('required|email'),
age: parseInlineRules('required|numeric|min:18|max:100'),
tags: parseInlineRules('array|minItems:1|maxItems:5'),
website: parseInlineRules('url')
};
const result = validator.validateRules(rules);Builder Pattern API
Fluent interface for building validation rules:
import { ValidatorBuilder } from '@teonord/validator';
const result = new ValidatorBuilder()
.setData({ username: 'john_doe', email: 'john@example.com' })
.addField('username', [
{ rule: 'required' },
{ rule: 'minLength', value: 3 },
{ rule: 'alphaDash' }
])
.addField('email', [
{ rule: 'required' },
{ rule: 'email' }
])
.setLanguage('en')
.validate();Functional Composition API
Composable validation pipelines:
import { createPipe, pipe, transformData, mapErrors, conditional } from '@teonord/validator';
// Individual validation pipes
const userValidation = createPipe({
name: [{ rule: 'required' }, { rule: 'minLength', value: 2 }],
email: [{ rule: 'required' }, { rule: 'email' }]
});
const addressValidation = createPipe({
street: [{ rule: 'required' }],
city: [{ rule: 'required' }],
country: [{ rule: 'required' }, { rule: 'in', value: ['US', 'CA', 'UK'] }]
});
const paymentValidation = createPipe({
payment_method: [{ rule: 'required' }],
amount: [{ rule: 'required' }, { rule: 'numeric' }, { rule: 'min', value: 1 }]
});
// Data transformation
const sanitizeData = (data: any) => ({
...data,
name: data.name?.trim().toLowerCase(),
email: data.email?.trim().toLowerCase(),
street: data.street?.trim()
});
// Error formatting
const formatErrors = (errors: any[]) =>
errors.map(error => ({
...error,
message: `${error.field}: ${error.message}`,
code: `VALIDATION_${error.rule.toUpperCase()}`
}));
// Complete validation pipeline
const completeValidation = pipe(
transformData(userValidation, sanitizeData),
addressValidation,
conditional(
(data) => data.requires_payment,
paymentValidation
)
);
const validationPipe = mapErrors(completeValidation, formatErrors);
// Usage
const userData = {
name: ' JOHN DOE ',
email: 'JOHN@EXAMPLE.COM',
street: '123 Main St',
city: 'New York',
country: 'US',
requires_payment: true,
payment_method: 'credit_card',
amount: 50
};
const result = validationPipe(userData);Rule Reference
String Rules
- required
- minLength:value
- maxLength:value
- length:value
- url
- ip
- uuid
- alpha
- alphaNumeric
- alphaDash
- regex:pattern
- startsWith:value
- endsWith:value
- contains:value
- notContains:value
- in:value1,value2,...
- notIn:value1,value2,...
Number Rules
- numeric
- integer
- float
- min:value
- max:value
- between:min,max
- positive
- negative
- multipleOf:value
Array Rules
- array
- minItems:value
- maxItems:value
- lengthItems:value
- includes:value
- excludes:value
- unique
Date Rules
- date
- before:date
- after:date
- betweenDates:start,end
File Rules
- file
- mime:type1,type2,...
- maxSize:bytes
- minSize:bytes
Boolean Rules
- boolean
- accepted
Conditional Rules
- requiredIf:field,value
- requiredUnless:field,value
- requiredWith:field
- requiredWithAll:field1,field2,...
- requiredWithout:field
- requiredWithoutAll:field1,field2,...
- same:field
- different:field
- gt:field
- gte:field
- lt:field
- lte:field
- when:condition
- unless:condition
Error Handling
const result = validator.validateRules({
email: [{ rule: 'required' }, { rule: 'email' }]
});
if (!result.isValid) {
result.errors.forEach(error => {
console.log(`Field: ${error.field}`);
console.log(`Rule: ${error.rule}`);
console.log(`Message: ${error.message}`);
console.log(`Value: ${error.value}`);
});
const apiErrors = result.errors.map(error => ({
field: error.field,
message: error.message,
code: error.rule
}));
}Internationalization
const validator = new Validator(data, {
language: 'fr',
customMessages: {
'email.required': {
en: 'Email address is required',
fr: 'L\'adresse email est requise',
es: 'La dirección de correo electrónico es obligatoria'
},
'email.email': {
en: 'Must be a valid email address',
fr: 'Doit être une adresse email valide',
es: 'Debe ser una dirección de correo electrónico válida'
}
}
});Custom Rules
const customRule = (value: any, params: any[], data: Record<string, any>) => {
if (value === 'custom') {
return true;
}
return 'Value must be "custom"';
};
validator.addCustomRule('customRule', customRule);
const result = validator.validateRules({
field: [{ rule: 'customRule' }]
});API Reference
Validator Class
Constructor
new Validator(data: Record<string, any>, options?: ValidatorOptions)Methods
- validateTemplate(template: any[]): ValidationResult
- validateRules(rules: Record<string, ValidationRuleConfig[]>): ValidationResult
- addCustomRule(name: string, rule: CustomRule): void
ValidatorBuilder Class
Methods
- setData(data: Record<string, any>): this
- addField(field: string, rules: ValidationRuleConfig[]): this
- setOptions(options: ValidatorOptions): this
- setLanguage(language: string): this
- build(): Validator
- validate(): ValidationResult
Functional API
- createPipe(rules, options): ValidationPipe
- createTemplatePipe(template, options): ValidationPipe
- pipe(...pipes): ValidationPipe
- mapErrors(pipe, mapper): ValidationPipe
- transformData(pipe, transformer): ValidationPipe
- conditional(condition, truePipe, falsePipe?): ValidationPipe
- mergePipes(...pipes): ValidationPipe