refactor: contains implemented as a standard keyword, #367
parent
cf3f1cea50
commit
41ecdaff7c
|
@ -70,13 +70,6 @@ function Ajv(opts) {
|
||||||
this._compilations = [];
|
this._compilations = [];
|
||||||
this.RULES = rules();
|
this.RULES = rules();
|
||||||
|
|
||||||
this.addKeyword('contains', {
|
|
||||||
type: 'array',
|
|
||||||
macro: function (schema) {
|
|
||||||
return { not: { items: { not: schema } } };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
opts.loopRequired = opts.loopRequired || Infinity;
|
opts.loopRequired = opts.loopRequired || Infinity;
|
||||||
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
|
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
|
||||||
this._metaOpts = getMetaSchemaOptions(this);
|
this._metaOpts = getMetaSchemaOptions(this);
|
||||||
|
|
|
@ -6,6 +6,7 @@ module.exports = {
|
||||||
allOf: require('../dotjs/allOf'),
|
allOf: require('../dotjs/allOf'),
|
||||||
anyOf: require('../dotjs/anyOf'),
|
anyOf: require('../dotjs/anyOf'),
|
||||||
const: require('../dotjs/const'),
|
const: require('../dotjs/const'),
|
||||||
|
contains: require('../dotjs/contains'),
|
||||||
dependencies: require('../dotjs/dependencies'),
|
dependencies: require('../dotjs/dependencies'),
|
||||||
'enum': require('../dotjs/enum'),
|
'enum': require('../dotjs/enum'),
|
||||||
format: require('../dotjs/format'),
|
format: require('../dotjs/format'),
|
||||||
|
|
|
@ -112,7 +112,7 @@ function compile(schema, root, localRefs, baseId) {
|
||||||
+ sourceCode;
|
+ sourceCode;
|
||||||
|
|
||||||
if (opts.processCode) sourceCode = opts.processCode(sourceCode);
|
if (opts.processCode) sourceCode = opts.processCode(sourceCode);
|
||||||
// console.log('\n\n\n *** \n', sourceCode);
|
// console.log('\n\n\n *** \n', JSON.stringify(sourceCode));
|
||||||
var validate;
|
var validate;
|
||||||
try {
|
try {
|
||||||
var makeValidate = new Function(
|
var makeValidate = new Function(
|
||||||
|
|
|
@ -11,7 +11,7 @@ module.exports = function rules() {
|
||||||
{ type: 'string',
|
{ type: 'string',
|
||||||
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
|
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
|
||||||
{ type: 'array',
|
{ type: 'array',
|
||||||
rules: [ 'maxItems', 'minItems', 'uniqueItems', 'items' ] },
|
rules: [ 'maxItems', 'minItems', 'uniqueItems', 'contains', 'items' ] },
|
||||||
{ type: 'object',
|
{ type: 'object',
|
||||||
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames',
|
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames',
|
||||||
{ 'properties': ['additionalProperties', 'patternProperties'] } ] },
|
{ 'properties': ['additionalProperties', 'patternProperties'] } ] },
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
{{# def.definitions }}
|
||||||
|
{{# def.errors }}
|
||||||
|
{{# def.setupKeyword }}
|
||||||
|
{{# def.setupNextLevel }}
|
||||||
|
|
||||||
|
|
||||||
|
{{
|
||||||
|
var $idx = 'i' + $lvl
|
||||||
|
, $dataNxt = $it.dataLevel = it.dataLevel + 1
|
||||||
|
, $nextData = 'data' + $dataNxt
|
||||||
|
, $currentBaseId = it.baseId
|
||||||
|
, $nonEmptySchema = {{# def.nonEmptySchema:$schema }};
|
||||||
|
}}
|
||||||
|
|
||||||
|
var {{=$errs}} = errors;
|
||||||
|
var {{=$valid}};
|
||||||
|
|
||||||
|
{{? $nonEmptySchema }}
|
||||||
|
{{# def.setCompositeRule }}
|
||||||
|
|
||||||
|
{{
|
||||||
|
$it.schema = $schema;
|
||||||
|
$it.schemaPath = $schemaPath;
|
||||||
|
$it.errSchemaPath = $errSchemaPath;
|
||||||
|
}}
|
||||||
|
|
||||||
|
for (var {{=$idx}} = 0; {{=$idx}} < {{=$data}}.length; {{=$idx}}++) {
|
||||||
|
{{
|
||||||
|
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true);
|
||||||
|
var $passData = $data + '[' + $idx + ']';
|
||||||
|
$it.dataPathArr[$dataNxt] = $idx;
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{# def.generateSubschemaCode }}
|
||||||
|
{{# def.optimizeValidate }}
|
||||||
|
|
||||||
|
if ({{=$nextValid}}) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{{# def.resetCompositeRule }}
|
||||||
|
{{= $closingBraces }}
|
||||||
|
|
||||||
|
if (!{{=$nextValid}}) {
|
||||||
|
{{??}}
|
||||||
|
if ({{=$data}}.length == 0) {
|
||||||
|
{{?}}
|
||||||
|
|
||||||
|
{{# def.error:'contains' }}
|
||||||
|
} else {
|
||||||
|
{{? $nonEmptySchema }}
|
||||||
|
{{# def.resetErrors }}
|
||||||
|
{{?}}
|
||||||
|
{{? it.opts.allErrors }} } {{?}}
|
||||||
|
|
||||||
|
{{# def.cleanUp }}
|
|
@ -97,6 +97,7 @@
|
||||||
additionalProperties: "'should NOT have additional properties'",
|
additionalProperties: "'should NOT have additional properties'",
|
||||||
anyOf: "'should match some schema in anyOf'",
|
anyOf: "'should match some schema in anyOf'",
|
||||||
const: "'should be equal to constant'",
|
const: "'should be equal to constant'",
|
||||||
|
contains: "'should contain a valid item'",
|
||||||
dependencies: "'should have {{? $deps.length == 1 }}property {{= it.util.escapeQuotes($deps[0]) }}{{??}}properties {{= it.util.escapeQuotes($deps.join(\", \")) }}{{?}} when property {{= it.util.escapeQuotes($property) }} is present'",
|
dependencies: "'should have {{? $deps.length == 1 }}property {{= it.util.escapeQuotes($deps[0]) }}{{??}}properties {{= it.util.escapeQuotes($deps.join(\", \")) }}{{?}} when property {{= it.util.escapeQuotes($property) }} is present'",
|
||||||
'enum': "'should be equal to one of the allowed values'",
|
'enum': "'should be equal to one of the allowed values'",
|
||||||
format: "'should match format \"{{#def.concatSchemaEQ}}\"'",
|
format: "'should match format \"{{#def.concatSchemaEQ}}\"'",
|
||||||
|
@ -132,6 +133,7 @@
|
||||||
additionalProperties: "false",
|
additionalProperties: "false",
|
||||||
anyOf: "validate.schema{{=$schemaPath}}",
|
anyOf: "validate.schema{{=$schemaPath}}",
|
||||||
const: "validate.schema{{=$schemaPath}}",
|
const: "validate.schema{{=$schemaPath}}",
|
||||||
|
contains: "validate.schema{{=$schemaPath}}",
|
||||||
dependencies: "validate.schema{{=$schemaPath}}",
|
dependencies: "validate.schema{{=$schemaPath}}",
|
||||||
'enum': "validate.schema{{=$schemaPath}}",
|
'enum': "validate.schema{{=$schemaPath}}",
|
||||||
format: "{{#def.schemaRefOrQS}}",
|
format: "{{#def.schemaRefOrQS}}",
|
||||||
|
@ -166,6 +168,7 @@
|
||||||
additionalProperties: "{ additionalProperty: '{{=$additionalProperty}}' }",
|
additionalProperties: "{ additionalProperty: '{{=$additionalProperty}}' }",
|
||||||
anyOf: "{}",
|
anyOf: "{}",
|
||||||
const: "{}",
|
const: "{}",
|
||||||
|
constains: "{}",
|
||||||
dependencies: "{ property: '{{= it.util.escapeQuotes($property) }}', missingProperty: '{{=$missingProperty}}', depsCount: {{=$deps.length}}, deps: '{{= it.util.escapeQuotes($deps.length==1 ? $deps[0] : $deps.join(\", \")) }}' }",
|
dependencies: "{ property: '{{= it.util.escapeQuotes($property) }}', missingProperty: '{{=$missingProperty}}', depsCount: {{=$deps.length}}, deps: '{{= it.util.escapeQuotes($deps.length==1 ? $deps[0] : $deps.join(\", \")) }}' }",
|
||||||
'enum': "{ allowedValues: schema{{=$lvl}} }",
|
'enum': "{ allowedValues: schema{{=$lvl}} }",
|
||||||
format: "{ format: {{#def.schemaValueQS}} }",
|
format: "{ format: {{#def.schemaValueQS}} }",
|
||||||
|
|
|
@ -90,7 +90,6 @@ var {{=$valid}};
|
||||||
$it.errSchemaPath = $errSchemaPath;
|
$it.errSchemaPath = $errSchemaPath;
|
||||||
}}
|
}}
|
||||||
{{# def.validateItems: 0 }}
|
{{# def.validateItems: 0 }}
|
||||||
{{# def.ifResultValid }}
|
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
{{? $breakOnError }}
|
{{? $breakOnError }}
|
||||||
|
|
|
@ -230,7 +230,7 @@
|
||||||
|
|
||||||
{{# def.cleanUp }}
|
{{# def.cleanUp }}
|
||||||
|
|
||||||
{{? $top && $breakOnError }}
|
{{? $top }}
|
||||||
{{# def.finalCleanUp }}
|
{{# def.finalCleanUp }}
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
|
|
|
@ -259,13 +259,13 @@ describe('boolean schemas', function() {
|
||||||
|
|
||||||
describe('in contains', function() {
|
describe('in contains', function() {
|
||||||
describe('schema = true', function() {
|
describe('schema = true', function() {
|
||||||
it('should be valid with any property', function() {
|
it('should be valid with any items', function() {
|
||||||
ajvs.forEach(test(true, true));
|
ajvs.forEach(test(true, true));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('schema = false', function() {
|
describe('schema = false', function() {
|
||||||
it('should be invalid with any property', function() {
|
it('should be invalid with any items', function() {
|
||||||
ajvs.forEach(test(false, false));
|
ajvs.forEach(test(false, false));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
"data": [1, 2, 3, 4],
|
"data": [1, 2, 3, 4],
|
||||||
"valid": false
|
"valid": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "empty array is invalid",
|
||||||
|
"data": [],
|
||||||
|
"valid": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "not array is valid",
|
"description": "not array is valid",
|
||||||
"data": {},
|
"data": {},
|
||||||
|
|
Loading…
Reference in New Issue