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