Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Lightweight validator supporting Language Independent Validation Rules Specification
LIVR.Validator - Lightweight JavaScript validator supporting Language Independent Validation Rules Specification (LIVR).
There are 2 implementations:
Common usage:
import LIVR from 'livr';
LIVR.Validator.defaultAutoTrim(true);
const validator = new LIVR.Validator({
name: 'required',
email: ['required', 'email'],
gender: { one_of: ['male', 'female'] },
phone: { max_length: 10 },
password: ['required', { min_length: 10 }],
password2: { equal_to_field: 'password' },
});
const validData = validator.validate(userData);
if (validData) {
saveUser(validData);
} else {
console.log('errors', validator.getErrors());
}
All standard rules are supported in camel case as well (Validator.registerDefaultRules always does autocamelization):
Camel case names are closer to JS naming conventions but underscore rule names are more compatible with LIVR spec.
import LIVR from 'livr';
LIVR.Validator.defaultAutoTrim(true);
const validator = new LIVR.Validator({
name: 'required',
email: ['required', 'email'],
gender: { oneOf: ['male', 'female'] },
phone: { maxLength: 10 },
password: ['required', { minLength: 10 }],
password2: { equalToField: 'password' },
});
const validData = validator.validate(userData);
if (validData) {
saveUser(validData);
} else {
console.log('errors', validator.getErrors());
}
Common usage of async version:
import LIVR from 'livr/async';
LIVR.AsyncValidator.defaultAutoTrim(true);
const validator = new LIVR.AsyncValidator({
name: 'required',
email: ['required', 'email'],
gender: { one_of: ['male', 'female'] },
phone: { max_length: 10 },
password: ['required', { min_length: 10 }],
password2: { equal_to_field: 'password' },
});
try {
const validData = await validator.validate(userData);
saveUser(validData);
} catch (errors) {
console.log('errors', errors);
}
You can use modifiers separately or can combine them with validation:
const validator = new LIVR.Validator({
email: ['required', 'trim', 'email', 'to_lc'],
});
Feel free to register your own rules:
You can use aliases(preferable, syntax covered by the specification) for a lot of cases:
const validator = new LIVR.Validator({
password: ['required', 'strong_password'],
});
validator.registerAliasedRule({
name: 'strong_password',
rules: { min_length: 6 },
error: 'WEAK_PASSWORD',
});
Or you can write more sophisticated rules directly:
const validator = new LIVR.Validator({
password: ['required', 'strong_password'],
});
validator.registerRules({
strong_password() {
return (value) => {
// We already have "required" rule to check that the value is present
if (value === undefined || value === null || value === '') return;
if (value.length < 6) {
return 'WEAK_PASSWORD';
}
};
},
});
Or you can write more sophisticated async rules as well:
const validator = new LIVR.AsyncValidator({
userId: ['required', 'valid_user_id'],
});
validator.registerRules({
valid_user_id() {
return async (value) => {
// We already have "required" rule to check that the value is present
if (value === undefined || value === null || value === '') return;
const user = await Users.findUserById(value);
if (!user) {
return 'WRONG_USER_ID';
}
};
},
});
If you use LIVR in browser, you can import only the rules you use (it can reduce budle size a little bit):
import Validator from 'livr/lib/Validator';
Validator.registerDefaultRules({
required: require('livr/lib/rules/common/required'),
email: require('livr/lib/rules/special/email'),
one_of: require('livr/lib/rules/string/one_of'),
min_length: require('livr/lib/rules/string/min_length'),
max_length: require('livr/lib/rules/string/max_length'),
equal_to_field: require('livr/lib/rules/special/equal_to_field'),
});
Validator.defaultAutoTrim(true);
// Anywhere in your app
import Validator from 'livr/lib/Validator';
const validator = new Validator({
name: 'required',
email: ['required', 'email'],
gender: { one_of: ['male', 'female'] },
phone: { max_length: 10 },
password: ['required', { min_length: 10 }],
password2: { equal_to_field: 'password' },
});
const validData = validator.validate(userData);
if (validData) {
saveUser(validData);
} else {
console.log('errors', validator.getErrors());
}
See LIVR Specification and rules documentation for detailed documentation and list of supported rules.
Features:
JavaScript version extra features:
LIVR supports async validation but it was added only in v2.5. So, it uses a little bit different API.
What you need to know about implementation:
Usage example:
import LIVR from 'livr/async';
LIVR.AsyncValidator.defaultAutoTrim(true);
const validator = new LIVR.AsyncValidator({
name: 'required',
email: ['required', 'email'],
});
try {
const validData = await validator.validate(userData);
saveUser(validData);
} catch (errors) {
console.log('errors', errors);
}
npm install livr
You can find prebuilt browser versions in "dist" folder
Constructor creates validator objects. rules - validations rules. Rules description is available here - https://livr-spec.org/
Supported options:
Instead of "options" object "isAutoTrim" boolean value can be passed for compatibility with previous API. if isAutoTrim is undefined(or null) then defaultAutoTrim value will be used.
alias - is a plain javascript object that contains: name, rules, error (optional).
LIVR.Validator.registerAliasedDefaultRule({
name: 'valid_address',
rules: {
nested_object: {
country: 'required',
city: 'required',
zip: 'positive_integer',
},
},
});
Then you can use "valid_address" for validation:
{
address: 'valid_address';
}
You can register aliases with own errors:
LIVR.Validator.registerAliasedDefaultRule({
name: 'adult_age'
rules: [ 'positive_integer', { min_number: 18 } ],
error: 'WRONG_AGE'
});
All rules/aliases for the validator are equal. The validator does not distinguish "required", "list_of_different_objects" and "trim" rules. So, you can extend validator with any rules/alias you like.
Note: Each rule which contains uderscore in name will be additionally registered using camel case name if there is no such rule name already.
ruleBuilder - is a function reference which will be called for building single rule validator.
Note: Each rule which contains uderscore in name will be additionally registered using camel case name if there is no such rule name already.
LIVR.Validator.registerDefaultRules({
my_rule(arg1, arg2, arg3, ruleBuilders) {
// ruleBuilders - are rules from original validator
// to allow you create new validator with all supported rules
// const validator = new LIVR.Validator(livr).registerRules(ruleBuilders).prepare();
return (value, allValues, outputArr) => {
if (notValid) {
return 'SOME_ERROR_CODE';
} else {
}
};
},
});
Then you can use "my_rule" for validation:
{
name1: 'my_rule' // Call without parameters
name2: { 'my_rule': arg1 } // Call with one parameter.
name3: { 'my_rule': [arg1] } // Call with one parameter.
name4: { 'my_rule': [ arg1, arg2, arg3 ] } // Call with many parameters.
}
Here is "max_number" implemenation:
function maxNumber(maxNumber) {
return (value) => {
// We do not validate empty fields. We have "required" rule for this purpose
if (value === undefined || value === null || value === '') return;
// return error message
if (value > maxNumber) return 'TOO_HIGH';
};
}
LIVR.Validator.registerDefaultRules({ max_number: maxNumber });
All rules for the validator are equal. The validator does not distinguish "required", "list_of_different_objects" and "trim" rules. So, you can extend validator with any rules you like.
returns object containing all default ruleBuilders for the validator. You can register new rule or update existing one with "registerRules" method.
Enables or disables automatic trim for input data. If is on then every new validator instance will have auto trim option enabled
List of useful utils for writing your rules (see source code)
Parses all validation rules to make subsequent calls faster. This step is always automatically called on first call of validator.validate(input) but you can call it manually if you want to warm up your validator object before validation was called. Usually, it is useful in several cases:
Validates user input. On success returns validData (contains only data that has described validation rules). On error return false.
const validData = validator.validate(input);
if (validData) {
// use validData
} else {
const errors = validator.getErrors();
}
for AsyncValidator
try {
const validData = await validator.validate(input);
// use validData
} catch (errors) {
// handle errors
}
Returns errors object.
{
"field1": "ERROR_CODE",
"field2": "ERROR_CODE",
...
}
For example:
{
"country": "NOT_ALLOWED_VALUE",
"zip": "NOT_POSITIVE_INTEGER",
"street": "REQUIRED",
"building": "NOT_POSITIVE_INTEGER"
}
ruleBuilder - is a function reference which will be called for building single rule validator.
See "LIVR.Validator.registerDefaultRules" for rules examples.
alias - is a composite validation rule.
See "LIVR.Validator.registerAliasedDefaultRule" for rules examples.
returns object containing all ruleBuilders for the validator. You can register new rule or update existing one with "registerRules" method.
LIVR is fast but you should be aware about following:
Do not construct Validator for each validation call. Construct object once for each schema and reuse validators with different inputs. "validator.validate(input)" is very fast.
In some cases you need to construct object each time, it is slower but still ok. It still will be twice faster than "Joi". LIVR validator preparation (rules compile step) is 100 time faster than "fastest-validator" compile time.
koorchik (Viktor Turskyi)
eNdiD
Please report any bugs or feature requests to Github https://github.com/koorchik/js-validator-livr
FAQs
Lightweight validator supporting Language Independent Validation Rules Specification
The npm package livr receives a total of 9,341 weekly downloads. As such, livr popularity was classified as popular.
We found that livr demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.