lite-form-validator
v0.1.6
Published
a framework agnostic typescript package for validating html forms
Downloads
622
Maintainers
Readme
Lite Form Validator
A framework-agnostic TypeScript validator for validating HTML form payloads using declarative rules.
- No dependencies
- Fully typed
- Synchronous
- Works with plain objects (no DOM coupling)
Installation
npm install lite-form-validatorBasic JavaScript Usage
import { LiteFormValidator } from "lite-form-validator";
const validator = new LiteFormValidator({
rules: {
email: { required: true, type: String },
date_of_birth: { required: true, type: Date, allowStringDate: true },
password_confirmation: { required: true, type: String, },
password: { required: true, type: String },
age: { type: Number, validate: (value) => value === 18 }
}
});
const payload = {
email: "[email protected]",
password_confirmation: 'pass123@1',
password: 123,
date_of_birth: '2026-02-04T15:44:40.682Z',
age: 19
};
// --------- validation ---------
validator.validateField("password", 122); // password must be of valid type String
validator.validate(payload); // false
validator.errors; // { password: 'password must be of valid type String', age: 'age does not match the requirements' }
validator.errorKeys; // [ 'password', 'age' ]Basic React Usage
import React, { useState } from 'react';
import { useLiteFormValidator } from 'lite-form-validator';
export function TestForm() {
const [form, setForm] = useState({ email: '', age: 0, name: '' });
const { validate, validateField, errors, isValid, clearErrors } = useLiteFormValidator({
rules: {
email: { type: String, required: true, pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
age: { type: Number, required: true, min: 18, max: 120, allowStringNumber: true, message: 'Age must be 18–120' },
name: { type: String, minLength: 2, maxLength: 50 },
},
messages: { required: 'This field is required' },
});
const handleChange = (f: keyof typeof form) => (e: React.ChangeEvent<HTMLInputElement>) => setForm({ ...form, [f]: e.target.value });
const handleBlur = (f: keyof typeof form) => () => validateField(f, form[f]);
const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (validate(form)) console.log(form); };
return (
<form onSubmit={handleSubmit}>
{['email', 'age', 'name'].map((field) => (
<div key={field}>
<label>{field}</label>
<input
type={field === 'age' ? 'number' : 'text'}
value={form[field as keyof typeof form]}
onChange={handleChange(field as keyof typeof form)}
onBlur={handleBlur(field as keyof typeof form)}
style={{ borderColor: errors[field] ? 'red' : '#ccc' }}
/>
{errors[field] && <div style={{ color: 'red' }}>{errors[field]}</div>}
</div>
))}
<button type="submit" disabled={!isValid}>Submit</button>
<button type="button" onClick={clearErrors}>Clear Errors</button>
<div>Form is {isValid ? '✅ Valid' : '❌ Invalid'}</div>
</form>
);
}Constructor
new LiteFormValidator(config)Config
{
rules: ValidationRules;
messages?: {
required?: string;
error?: string;
};
}rules(required) — validation rules per fieldmessages(optional) — global fallback error messagesrequired→ used when a required field is missingerror→ used for type / rule failures
Validation Methods
validate(payload)
Validates an entire payload.
validator.validate(payload);Arguments
payload: Partial<FormValues<T>>
Returns
true→ payload is validfalse→ payload failed validation
Side effects
- Populates
validator.errors - Populates
validator.errorKeys
validateField(key, value)
Validates a single field in isolation.
validator.validateField("email", "[email protected]");Returns
null→ field is validstring→ validation error message
This method does not permanently mutate
errors
Validation Results
errors
An object containing error messages per field.
{
email?: string;
password?: string;
}errorKeys
An array of field names that failed validation.
["email", "password"]Validation Rules
Each field accepts the following rule options:
{
type: String | Number | Boolean | Date;
required?: boolean;
// Number rules
min?: number;
max?: number;
// String rules
minLength?: number;
maxLength?: number;
pattern?: RegExp;
// Type coercion
allowStringNumber?: boolean;
allowStringDate?: boolean;
// Custom validation
validate?: (value: any) => boolean | string;
// Field-level custom message
message?: string;
}Type Handling
Numbers
- Accepts
number - Optionally accepts numeric strings if
allowStringNumber: true
Dates
- Accepts
Dateinstances - Optionally accepts ISO date strings if
allowStringDate: true
Custom Validation
password: {
type: String,
validate: (value) => value.length >= 8 || "* must be at least 8 characters",
}- Returning
false→ generic error - Returning a
string→ custom error message *is replaced with the field name
Custom Error Messages
Global messages
const validator = new LiteFormValidator({
rules: {
email: { required: true, type: String },
},
messages: {
required: "* is required",
error: "* is invalid",
},
});Field-level messages
email: {
type: String,
required: true,
message: "Please provide a valid email address",
}❌ Don’ts
Do NOT destructure class methods
Destructuring loses this context and breaks validation.
❌ const { validate } = new LiteFormValidator({ rules: {} });
❌ validate(payload);✅ Correct usage
const validator = new LiteFormValidator({ rules: {} });
validator.validate(payload);
validator.errors;Notes
- Validation is synchronous
- Only fields defined in
rulesare validated - Extra payload fields are ignored
- Missing optional fields are skipped
