sculp v3.0.0
sculp

Most functional javascript object validation library
Description
Sculp is a library that will help you cast and/or validate input data according to your schema. Typical applications include form management, validating object before saving to DB, casting HTTP request parameters to proper types, and many more.
Compared to other object validation libraries Sculp provides unique features such as conditional validation rules, incremental validation and object structure reuse.
TOC
- Features
- Installation
- Example
- Schema structure
- API
- Custom types and validations
- Field state object
Features
- Declarative schema. Schemas are simple objects, with a very easy-to-read structure. This means you can reuse them, clone them, extend them, and do with them whatever you want.
- Support for custom types and validation rules. Any crazy rules you need. Array should be of odd length and its items should start with an underscore? No problem.
- Conditional rules. Some field is present only if some checkbox field is on? No problem.
- Fast incremental validation. You need to validate some gigantic form on the fly while user is editing it? Incremental validation ensures that only necessary fields and validation rules are recalculated.
- Object structure reuse. To find out if your objects or validation rules have changed after last update by user, all you need is strict comparison. This makes this library very React-friendly.
Installation
$ npm install --save sculpExample
import { validate, Type, Presence } from 'sculp';
const schema = {
type : Type.OBJECT,
properties : {
name : {
type : Type.STRING,
$lengthmin : 1
$presence : Presence.REQUIRED
},
gender : {
type : Type.STRING_NET,
transform : (v) => v && v.toLowerCase(),
$values : [ 'male', 'female' ]
},
age : {
type : Type.NUMBER,
$min : 0
},
isAdult : {
type : Type.BOOLEAN,
compute : (fieldAccessor) =>
fieldAccessor('^.age') >= 18
}
}
}
const result = validate({ name : 'John', gender : ' MALE ', age : '21' }, schema);
// returns { name : 'John', gender : 'male', age : 21, isAdult : true }
const result = validate({ age : -5 }, schema);
// throws sculp.ValidationError with errors arrayThis example schema defines the following constraints:
nameproperty- should be string
- should be not empty (minimum length is 1)
- should be defined
genderproperty- should be string
- will be trimmed and converted to lowercase
- should be one of 2 values ("male", "female")
ageproperty- should be not negative
isAdultproperty- boolean computed value
Schema structure
Schemas are plain javascript objects that can have following definition properties:
type
The type of a value. Should be string value.
If type is not defined is defaults to Type.ANY_VALUE.
There are 11 available types and you can define your own new types through defining custom casts.
Predefined types available under Type enumeration:
import { Type } from 'sculp';List of available types:
Type.STRINGString type.Type.STRING_NETString-not-empty-and-trimmed type. The same as Type.STRING but value gets trimmed and removed if it is an empty string.Type.NUMBERNumber type.Type.BOOLEANBoolean type.Type.FUNCTIONFunction type.Type.DATEDate type.Type.OBJECTObject type. For this type you need to provide schemas for all properties usingpropertiesfield.Type.GROUPThe same asType.OBJECTbut this type represents an object as just a group of fields and not as some entity. The difference is the validation of properties forundefinedvalues. ForType.GROUPproperties are validated and forType.OBJECTthey are not.Type.ARRAYArray type. For this type you need to provide schema for array item usingitemsfield.Type.ANY_VALUEValue of any type.Type.ANY_OBJECTObject with any properties. Nopropertiesfield needed.
name
The name of a value/field. Should be string or function returning string.
meta
Any additional information that you want to attach to this value/field.
precision
Can be defined for Type.NUMBER. Truncates the value to specified precision.
valid
If any validation (other than type validation) fails on this field, value will be replaced by valid value if it is defined.
initial
Provide initial value. You can get initial value for whole schema with getInitial(schema) function.
removeEmpty
Used for Type.ARRAY, Type.OBJECT and Type.GROUP only. Overrides removeEmpty option for this value/field.
If removeEmpty is true empty objects and arrays are removed.
Default value is false.
properties
Used for Type.OBJECT and Type.GROUP only.
The value should be an object that provides schemas for available properties in the form of { prop1 : prop1Schema, prop2 : prop2Schema, ... }.
items
Used for Type.ARRAY only. The value should be a schema for array items.
transform
A function or array of functions to transform value (e.g. convert string to lowercase). Those functions take current value as an argument and should return transformed value.
compute
A function of array of functions to compute value (e.g. set object field value to some value derived on the values of other fields). Those functions take field accessor function as an argument and should return computed value.
$... validation rule properties
All schema properties that start with $ are validation rules. There are several predefined validations, and you can provide your custom validations using options or defining $custom validation.
Any validation rule expects some rule value that value will be validated against. For example for $values rule value is expected to be an array of possible values ({ $values : [ 1, 2, 3 ] }).
The value $... property should be a rule value or a function computing rule value.
Example:
const schema = {
type : Type.OBJECT,
properties : {
string : {
type : Type.STRING,
$lengthmin : 5,
$presence : {
value : Presence.REQUIRED,
message : '"String" property is required!'
}
},
longerString : {
type : Type.STRING,
$lengthmin : (fa) => {
const stringPropValue = fa('^.string') || '';
return stringPropValue.length + 1;
}
}
}
}Available validations:
$presenceValidates value presence. Available rule values arePresence.REQUIRED,Presence.OPTIONALandPresence.ABSENT.$valuesValidates that value is one of provided values. Rule value should be an array.$regexpValidates that value matches regular expression. Rule value should be a string or RegExp.$lengthValidates length of a value. Can be used for strings and arrays. Rule value is a number for exact length or an object withminand/ormaxproperties for providing min and max limits (e.g.$length : { min : 1, max : 10 }).$lengthminValidates that value.length >= rule value. Can be used for strings and arrays.$lengthmaxValidates that value.length <= rule value. Can be used for strings and arrays.$neValidates that value !== rule value.$minValidates that number value >= rule value.$maxValidates that number value <= rule value.$gtValidates that number value > rule value.$ltValidates that number value < rule value.
$custom custom validation rule
The $custom property value should be a function that returns error message string when validation fails and undefined otherwise.
Function takes field accessor function as a first argument.
Example:
const schema = {
type : Type.STRING,
$custom : (fa) => {
const value = fa() || '';
return value[0] == 'A' ? undefined : 'String should start with an A letter'
}
}API
Static functions
validate()
validate(value: any, schema: object, ?options: object): anyValidates value with schema and returns validated value or throws ValidationError when validation fails. Takes options as an optional argument.
Example:
validate('valid str', { type : Type.STRING, $length : 9 }, { strict : true });
// returns string 'valid str'
validate('invalid str', { type : Type.STRING, $length : 9 }, { strict : true });
// throws ValidationErrortryValidate()
tryValidate(value: any, schema: object, ?options: object): objectNot throwing version of validate.
Validates value with schema and returns object with result, errors and fieldsState fields. Takes options as an optional argument.
getSchemaValue(), getFieldName(), getFieldPresence()
getSchemaValue(value: any, schema: object, path: string, property: string): any
getFieldName(value: any, schema: object, path: string): string
getFieldPresence(value: any, schema: object, path: string): stringTODO : write description The use of this functions is discouraged.
getInitial()
getInitial(schema: object): anyGet initial value for schema. Constructed from initial property values of schema.
getSubSchema()
getSubSchema(schema: object, path: string): objectGet sub-schema for schema.
Example:
getSubSchema(schema, '.some.nested.field'); // returns schema for subfield 'some.nested.field'setDefaultOptions()
setDefaultOptions(options: object): undefinedSets application-wide default options for validate and tryValidate methods as well as Sculp constructor.
Example:
setDefaultOptions({
strict : true,
casts : { ... },
messages : russianLangMessages
});Sculp class
constructor()
Sculp(value: any, schema: object, ?options: object): undefinedConstructs new Sculp instance.
Sculp instance allows you to perform fast incremental validations on your value when it changes. Takes options as an optional argument.
Example:
const value = { ... };
const sculp = new Sculp(value, schema);
sculp.validate(); // returns validation result for value
sculp.setField('.some.deep.nested.field', newValue); // mutates some field of value object
sculp.validate(); // returns validation result for current valuevalidate()
Sculp.prototype.validate(): anyThe same as static validate but runs validation on current value using schema and options provided to Sculp constructor.
Returns validated value or throws ValidationError when validation fails.
Example:
const sculp = new Sculp({ field : 1 }, schema);
sculp.setField('.field', 2); // mutates field of value object
sculp.validate(); // returns validation result for current valuetryValidate()
Sculp.prototype.tryValidate(): objectThe same as static tryValidate but runs validation on current value using schema and options provided to Sculp constructor.
Returns object with result, errors and fieldsState fields.
Example:
const sculp = new Sculp({ field : 1 }, schema);
sculp.setField('.field', 2); // mutates field of value object
sculp.tryValidate(); // returns object with validation result and errorsgetValue()
Sculp.prototype.getValue(): anyReturns current value.
Example:
const sculp = new Sculp({ field : 1 }, schema);
sculp.setField('.field', 2);
sculp.getValue(); // returns { field : 2 }setValue()
Sculp.prototype.setValue(newValue: any): undefinedReplaces current value and clears all internal Sculp instance caches.
Example:
const sculp = new Sculp({ field : 1 }, schema);
sculp.validate(); // returns validation result for { field : 1 }
sculp.setValue({ newField : 2 }); // replaces
sculp.validate(); // returns validation result for { newField : 2 }setField(), setFields()
Sculp.prototype.setField(path: string, value: any): undefined
Sculp.prototype.setFields(values: object): undefinedMutates current value according to provided parameters.
setField mutates one field, setFields can mutate several fields at once.
Note that path parameter and values keys for mutating fields must start with a dot (i.e. '.field' and { '.field' : newValue }).
Example:
const sculp = new Sculp({ list : [ {} ] }, schema);
sculp.setField('.list[0].a', 1);
sculp.setFields({ '.list[0].b' : 2, '.list[0].c' : 3 });
sculp.getValue(); // returns { list : [ { a : 1, b : 2, c : 3 } ] }getFieldState()
Sculp.prototype.getFieldState(path: string): objectReturns field state object for path path of current value.
See Field state object.
getSchemaValue(), getFieldName(), getFieldPresence()
Sculp.prototype.getSchemaValue(path: string, property: string): any
Sculp.prototype.getFieldName(path: string): string
Sculp.prototype.getFieldPresence(path: string): stringWhen you need to get value of some schema definition property or validation rule you can use getSchemaValue method. Useful to get values of conditional rules. For example, if you have conditional $presence rule for some field you can get current presence with getSchemaValue(path, '$presence').
Example:
const sculp = new Sculp(value, schema);
sculp.getSchemaValue('.someField', '$values');
sculp.getFieldName('.someField'); // the same as sculp.getSchemaValue('.someField', 'name');
sculp.getFieldPresence('.someField'); // the same as sculp.getSchemaValue('.someField', '$presence');Field Accessor Functions
Field accessor is a function that is passed to rule value functions and compute functions. Field accessor allows you to access other field values.
Field accessor usage:
fieldAccessor(); // returns value of current field
fieldAccessor('.prop'); // returns field 'prop' of current field
fieldAccessor('^.prop'); // returns field 'prop' of parent value
fieldAccessor('^^.prop'); // returns field 'prop' of root valueExamples:
const schema = {
type : Type.OBJECT,
properties : {
a : { type : Type.STRING },
b : {
type : Type.OBJECT,
properties : {
c : {
compute : (fa) => 'prefix' + fa() // returns value of this field
},
d : {
compute : (fa) => fa('^^.a') // returns field 'a'
},
e : {
compute : (fa) => fa('^.c') // returns field 'b.c'
}
}
}
}
}Options
These options can be provided to validate, tryValidate static functions and Sculp constructor.
If you need to set options application-wide use setDefaultOptions function.
messages
For i18n purposes you can provide your custom strings to use as error messages. Only English and Russian message strings are provided with the library right now. Default value is an object with English language error messages.
Example:
import russianMessages from 'sculp/lib/i18n/ru';
validate(value, schema, { messages : ruMessages });
// or
setDefaultOptions({ messages : ruMessages });strict
By default Sculp will try to cast value to required type. For example it will return 42 when validating string '42' with { type : Type.NUMBER } schema.
If you don't want Sculp to try to cast values to required types you can set strict option to true.
Default value is false.
casts and castsStrict
Option for providing casts for custom types. See Custom types and validations.
validations
Option for providing custom validations. See Custom types and validations.
Custom types and validations
Custom types are provided with casts and castsStrict options.
You should provide a cast function for each custom type. If value is not of your custom type your cast function should return special CAST_ERROR value.
casts option is used for strict = false (default value) validations and castsStrict is used when strict = true.
Custom validations are provided with validations option. Validation function takes field accessor as first argument and validation rule value as second. Validation function should return error message string when validation fails and undefined otherwise.
Example:
import { validate } from 'sculp';
import { CAST_ERROR } from 'sculp/lib/enums';
const options = {
casts : {
'INTEGER' : (v) => {
if (isNumber(v) && v === Math.round(v))
return v;
return CAST_ERROR;
}
},
validations : {
'divisible' : (fa, ruleValue) => {
if (value && value % ruleValue !== 0)
return `value is not divisible by ${ruleValue}`;
}
}
};
const schema = {
type : 'INTEGER',
$divisible : 3
}
validate(9, schema, options);Field state object
TODO: document.
Roadmap
- Partial validation support
- Computed schemas support
- Passing context
- Add popular validation rules
License
MIT © dettier
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago