Self-validation

master
Vitaliy Filippov 2019-09-22 02:14:18 +03:00
parent 9a67ab46ee
commit fd140bfa31
2 changed files with 30 additions and 6 deletions

View File

@ -5,8 +5,9 @@
* - Uses literal definitions (unlike, for example, Joi)
* - Simpler than JSON schema, but convertible to it
* - Supports comments and convenient user-readable validation errors
* - Coerces decimal strings to numbers
* - Coerces scalars to single-element arrays
* - Converts strings to numbers if possible
* - Converts scalars to single-element arrays
* - Validates its own meta-type
*
* (c) Vitaliy Filippov 2019+
*
@ -100,7 +101,7 @@ class ServerPropTypes
{
bad = {
path: [ i, ...(st.error.path||[]) ],
name: '№'+i + (st.error.name ? ' - '+st.error.name : ''),
name: '№'+(i+1) + (st.error.name ? ' - '+st.error.name : ''),
};
break;
}
@ -128,7 +129,7 @@ class ServerPropTypes
{
bad = {
path: [ i, ...(st.error.path||[]) ],
name: '№'+i + (st.error.name ? ' - '+st.error.name : ''),
name: '№'+(i+1) + (st.error.name ? ' - '+st.error.name : ''),
};
break;
}
@ -148,7 +149,7 @@ class ServerPropTypes
}
break;
case 'object':
if (typeof v != 'object' || v instanceof Array || type.required && !v)
if (v != null && typeof v != 'object' || v instanceof Array || type.required && !v)
{
bad = true;
}
@ -366,12 +367,21 @@ ServerPropTypes.metaType = {
spt: {
type: 'one',
of: [
{ comment: 'Reference to another type', type: 'object', items: {
type: { type: 'enum', of: [ 'ref' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
ref: { type: 'string', comment: 'Type reference', required: true },
} },
{ comment: 'Any type', type: 'object', items: {
type: { type: 'enum', of: [ 'any' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
comment: { type: 'string', comment: 'Item comment' },
} },
{ comment: 'String', type: 'object', items: {
type: { type: 'enum', of: [ 'string' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
regex: { type: 'string', comment: 'Regular expression' },
@ -379,12 +389,14 @@ ServerPropTypes.metaType = {
} },
{ comment: 'String-coded decimal', type: 'object', items: {
type: { type: 'enum', of: [ 'decimal' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
decimals: { type: 'int', comment: 'Allowed decimal places' },
} },
{ comment: 'Number', type: 'object', items: {
type: { type: 'enum', of: [ 'num' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
min: { type: 'num', comment: 'Minimum value' },
@ -392,6 +404,7 @@ ServerPropTypes.metaType = {
} },
{ comment: 'Integer', type: 'object', items: {
type: { type: 'enum', of: [ 'int' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
min: { type: 'int', comment: 'Minimum value' },
@ -399,16 +412,19 @@ ServerPropTypes.metaType = {
} },
{ comment: 'ID (positive integer or NULL)', type: 'object', items: {
type: { type: 'enum', of: [ 'id' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
} },
{ comment: 'Boolean', type: 'object', items: {
type: { type: 'enum', of: [ 'bool' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
} },
{ comment: 'Array', type: 'object', items: {
type: { type: 'enum', of: [ 'array' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
of: { type: 'ref', ref: 'anytype', required: true, comment: 'Array item type' },
@ -417,12 +433,14 @@ ServerPropTypes.metaType = {
} },
{ comment: 'Tuple (fixed-length array)', type: 'object', items: {
type: { type: 'enum', of: [ 'array' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
items: { type: 'array', of: { type: 'ref', ref: 'anytype' }, required: true, comment: 'Tuple item types' },
} },
{ comment: 'Unstructured hash', type: 'object', items: {
type: { type: 'enum', of: [ 'object' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
of: { type: 'ref', ref: 'anytype', required: true, comment: 'Hash item type' },
@ -431,18 +449,21 @@ ServerPropTypes.metaType = {
} },
{ comment: 'Structured object', type: 'object', items: {
type: { type: 'enum', of: [ 'object' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
items: { type: 'object', of: { type: 'ref', ref: 'anytype' }, required: true, comment: 'Field types' },
} },
{ comment: 'Enum of constants', type: 'object', items: {
type: { type: 'enum', of: [ 'enum' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
of: { type: 'array', minLength: 1, required: true, comment: 'Constants' },
of: { type: 'array', of: 'any', minLength: 1, required: true, comment: 'Constants' },
} },
{ comment: 'One of types', type: 'object', items: {
type: { type: 'enum', of: [ 'one' ] },
refs: { type: 'object', of: { type: 'ref', ref: 'anytype' } },
required: { type: 'bool', comment: 'Item is required' },
comment: { type: 'string', comment: 'Item comment' },
of: { type: 'array', of: { type: 'ref', ref: 'anytype' }, minLength: 1, required: true, comment: 'Type options' },

View File

@ -11,3 +11,6 @@ const type = {
};
console.log(JSON.stringify(spt.check({ type: 'object', items: type }, spt.metaType, { return_error: true }), null, 2));
// Self-validate!
console.log(JSON.stringify(spt.check(spt.metaType, spt.metaType, { return_error: true }), null, 2));