One, foreword
B-validate is a small and feature-rich type validation library with the following features:
- Chain calls
- Supports custom verification rules
- Support schema verification
- Support asynchronous verification
Its basic usage is as follows:
bv(123)
.number
.min(2)
.max(10)
.collect((error) => {
console.log(error); // { value: 123, type: 'number', message: '123 is not less than 10' }
// if no error, error equal to null
});
const error = bv('b-validate').string.isRequired.match(/validater/).end;
// { value: 'b-validate', type: 'string', message: '`b-validate` is not match pattern /validater/' }
Copy the code
Second, the Base Class
B-validate All data structures’ validation classes are extended based on the Base Class:
class Base { constructor(obj, options) { if (isObject(options) && isString(obj) && options.trim) { this.obj = obj.trim(); } else if (isObject(options) && options.ignoreEmptyString && obj === "") { this.obj = undefined; } else { this.obj = obj; } // Customize the verification message this.message = options.message; this.type = options.type; // This. Error = null; } get end() { return this.error; } addError(message) { if (! this.error && message) { this.error = { value: this.obj, type: this.type, message: this.message || `${this._not ? "[NOT MODE]:" : ""}${message}`, }; } } validate(expression, errorMessage) { const _expression = this._not ? expression : ! expression; if (_expression) { this.addError(errorMessage); } return this; } collect(callback) { callback && callback(this.error); }}Copy the code
The validation process is easy to understand, which is ** “output the final this.error message by calling various rules” **.
Class ArrayValidater extends Base {constructor(obj, options) {super(obj, {... options, type: 'array' }); this.validate( options && options.strict ? isArray(this.obj) : true, `Expect array type but got `${this.obj}`` ); } length(num) { return this.obj ? this.validate( this.obj.length === num, `Expect array length ${num} but got ${this.obj.length}` ) : this; } minLength(num) { return this.obj ? this.validate( this.obj.length >= num, `Expect min array length ${num} but got ${this.obj.length}` ) : this; }}Copy the code
For a particular data structure, the class’s constructor first validates its type and then extends the various validation rule methods.
Chain call
B-validate implements chained calls in the most common way: “Based on this scope.”
Constructor (obj, options) {} get not() {this._not =! this._not; // Return the current instance to provide a chained call to return this; } get isRequired() { if (isEmptyValue(this.obj) || isEmptyArray(this.obj)) { this.error = { value: this.obj, type: this.type, requiredError: true, message: this.message || `${this._not ? "[NOT MODE]:" : ""}${this.type} is required`, }; } // Return the current instance to provide a chained call to return this; }}Copy the code
Schema implementation
Schema differs from previous calls in that:
- Batch processing type verification
- Reduce manual chain calls through schema conventions
export class Schema { constructor(schema, options = {}) { this.schema = schema; this.options = options; } validate(values, callback) { if (! isObject(values)) { return; } const promises = []; let errors = null; Function setError(key, error) {if (! errors) { errors = {}; } if (! errors[key] || error.requiredError) { errors[key] = error; } } if (this.schema) { Object.keys(this.schema).forEach((key) => { if (isArray(this.schema[key])) { for (let i = 0; i < this.schema[key].length; i++) { const rule = this.schema[key][i]; const type = rule.type; const message = rule.message; }}}); } // omit some code callback && callback(errors); }}Copy the code
Under the premise of schema convention, the internal execution code can automatically traverse each rule, obtain corresponding this.error information through collect method, and finally call setError method to integrate into array output.
Five, the summary
The main points of this paper are as follows:
- Understand the core process of type validation
- A validation rule class that extends different data structures based on inheritance
- Implement chain calls based on this scope
- The verification process in batch data verification scenarios was optimized by the design of schema
For those interested in datatype validation libraries, don’t miss the joI library.
Finally, “If this article is helpful to you, please like, bookmark and share”.