feat: support boolean schemas in $ref
parent
225ef67ce5
commit
f1028c8411
|
@ -209,7 +209,7 @@ function compile(schema, root, localRefs, baseId) {
|
|||
|
||||
refCode = addLocalRef(ref);
|
||||
var v = resolve.call(self, localCompile, root, ref);
|
||||
if (!v) {
|
||||
if (v === undefined) {
|
||||
var localSchema = localRefs && localRefs[ref];
|
||||
if (localSchema) {
|
||||
v = resolve.inlineRef(localSchema, opts.inlineRefs)
|
||||
|
@ -218,7 +218,7 @@ function compile(schema, root, localRefs, baseId) {
|
|||
}
|
||||
}
|
||||
|
||||
if (v) {
|
||||
if (v !== undefined) {
|
||||
replaceLocalRef(ref, v);
|
||||
return resolvedRef(v, refCode);
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ function compile(schema, root, localRefs, baseId) {
|
|||
}
|
||||
|
||||
function resolvedRef(refVal, code) {
|
||||
return typeof refVal == 'object'
|
||||
return typeof refVal == 'object' || typeof refVal == 'boolean'
|
||||
? { code: code, schema: refVal, inline: true }
|
||||
: { code: code, $async: refVal && refVal.$async };
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ function defaultCode(i) {
|
|||
|
||||
|
||||
function refValCode(i, refVal) {
|
||||
return refVal[i] ? 'var refVal' + i + ' = refVal[' + i + '];' : '';
|
||||
return refVal[i] === undefined ? '' : 'var refVal' + i + ' = refVal[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ function resolve(compile, root, ref) {
|
|||
|
||||
if (schema instanceof SchemaObject) {
|
||||
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
|
||||
} else if (schema) {
|
||||
} else if (schema !== undefined) {
|
||||
v = inlineRef(schema, this._opts.inlineRefs)
|
||||
? schema
|
||||
: compile.call(this, schema, root, undefined, baseId);
|
||||
|
@ -122,7 +122,7 @@ function getJsonPointer(parsedRef, baseId, schema, root) {
|
|||
if (part) {
|
||||
part = util.unescapeFragment(part);
|
||||
schema = schema[part];
|
||||
if (!schema) break;
|
||||
if (schema === undefined) break;
|
||||
if (schema.id && !PREVENT_SCOPE_CHANGE[part]) baseId = resolveUrl(baseId, schema.id);
|
||||
if (schema.$ref) {
|
||||
var $ref = resolveUrl(baseId, schema.$ref);
|
||||
|
@ -135,7 +135,7 @@ function getJsonPointer(parsedRef, baseId, schema, root) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (schema && schema != root.schema)
|
||||
if (schema !== undefined && schema !== root.schema)
|
||||
return { schema: schema, root: root, baseId: baseId };
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module.exports = {
|
|||
varOccurences: varOccurences,
|
||||
varReplace: varReplace,
|
||||
cleanUpCode: cleanUpCode,
|
||||
cleanUpVarErrors: cleanUpVarErrors,
|
||||
finalCleanUpCode: finalCleanUpCode,
|
||||
schemaHasRules: schemaHasRules,
|
||||
schemaHasRulesExcept: schemaHasRulesExcept,
|
||||
stableStringify: require('json-stable-stringify'),
|
||||
|
@ -150,16 +150,22 @@ var ERRORS_REGEXP = /[^v\.]errors/g
|
|||
, RETURN_VALID = 'return errors === 0;'
|
||||
, RETURN_TRUE = 'validate.errors = null; return true;'
|
||||
, RETURN_ASYNC = /if \(errors === 0\) return true;\s*else throw new ValidationError\(vErrors\);/
|
||||
, RETURN_TRUE_ASYNC = 'return true;';
|
||||
, RETURN_TRUE_ASYNC = 'return true;'
|
||||
, ROOTDATA_REGEXP = /[^A-Za-z_$]rootData[^A-Za-z0-9_$]/g
|
||||
, REMOVE_ROOTDATA = /if \(rootData === undefined\) rootData = data;/;
|
||||
|
||||
function cleanUpVarErrors(out, async) {
|
||||
function finalCleanUpCode(out, async) {
|
||||
var matches = out.match(ERRORS_REGEXP);
|
||||
if (!matches || matches.length !== 2) return out;
|
||||
return async
|
||||
? out.replace(REMOVE_ERRORS_ASYNC, '')
|
||||
.replace(RETURN_ASYNC, RETURN_TRUE_ASYNC)
|
||||
: out.replace(REMOVE_ERRORS, '')
|
||||
.replace(RETURN_VALID, RETURN_TRUE);
|
||||
out = async
|
||||
? out.replace(REMOVE_ERRORS_ASYNC, '')
|
||||
.replace(RETURN_ASYNC, RETURN_TRUE_ASYNC)
|
||||
: out.replace(REMOVE_ERRORS, '')
|
||||
.replace(RETURN_VALID, RETURN_TRUE);
|
||||
|
||||
matches = out.match(ROOTDATA_REGEXP);
|
||||
if (!matches || matches.length !== 3) return out;
|
||||
return out.replace(REMOVE_ROOTDATA, '');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
{{## def.cleanUp: {{ out = it.util.cleanUpCode(out); }} #}}
|
||||
|
||||
|
||||
{{## def.cleanUpVarErrors: {{ out = it.util.cleanUpVarErrors(out, $async); }} #}}
|
||||
{{## def.finalCleanUp: {{ out = it.util.finalCleanUpCode(out, $async); }} #}}
|
||||
|
||||
|
||||
{{## def.$data:
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
{{?}}
|
||||
|
||||
{{? typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref) }}
|
||||
{{ var $keyword = 'false schema'; }}
|
||||
{{# def.setupKeyword }}
|
||||
{{? it.schema === false}}
|
||||
{{ var $keyword = 'false schema'; }}
|
||||
{{# def.setupKeyword }}
|
||||
{{? it.isTop}}
|
||||
{{ $breakOnError = true; }}
|
||||
{{??}}
|
||||
|
@ -85,7 +85,7 @@
|
|||
|
||||
var vErrors = null; {{ /* don't edit, used in replace */ }}
|
||||
var errors = 0; {{ /* don't edit, used in replace */ }}
|
||||
if (rootData === undefined) rootData = data;
|
||||
if (rootData === undefined) rootData = data; {{ /* don't edit, used in replace */ }}
|
||||
{{??}}
|
||||
{{
|
||||
var $lvl = it.level
|
||||
|
@ -227,7 +227,7 @@
|
|||
{{# def.cleanUp }}
|
||||
|
||||
{{? $top && $breakOnError }}
|
||||
{{# def.cleanUpVarErrors }}
|
||||
{{# def.finalCleanUp }}
|
||||
{{?}}
|
||||
|
||||
{{
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
[
|
||||
{
|
||||
"description": "boolean schema = true in properties",
|
||||
"schema": {
|
||||
"$async": true,
|
||||
"properties": {
|
||||
"foo": true
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any data is valid",
|
||||
"data": { "foo": 1 },
|
||||
"valid": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "boolean schema = false in properties",
|
||||
"schema": {
|
||||
"$async": true,
|
||||
"properties": {
|
||||
"foo": false
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any property is invalid",
|
||||
"data": { "foo": 1 },
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "without property is valid",
|
||||
"data": { "bar": 1 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "empty object is valid",
|
||||
"data": {},
|
||||
"valid": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "boolean schema = true in $ref",
|
||||
"schema": {
|
||||
"$async": true,
|
||||
"$ref": "#/definitions/true",
|
||||
"definitions": {
|
||||
"true": true
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any data is valid",
|
||||
"data": 1,
|
||||
"valid": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "boolean schema = false in $ref",
|
||||
"schema": {
|
||||
"$async": true,
|
||||
"$ref": "#/definitions/false",
|
||||
"definitions": {
|
||||
"false": false
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any data is invalid",
|
||||
"data": 1,
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "boolean schema = true in properties with $ref",
|
||||
"schema": {
|
||||
"$async": true,
|
||||
"properties": {
|
||||
"foo": { "$ref": "#/definitions/foo" }
|
||||
},
|
||||
"definitions": {
|
||||
"foo": true
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any data is valid",
|
||||
"data": { "foo": 1 },
|
||||
"valid": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "boolean schema = false in properties with $ref",
|
||||
"schema": {
|
||||
"$async": true,
|
||||
"properties": {
|
||||
"foo": { "$ref": "#/definitions/foo" }
|
||||
},
|
||||
"definitions": {
|
||||
"foo": false
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any property is invalid",
|
||||
"data": { "foo": 1 },
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "without property is valid",
|
||||
"data": { "bar": 1 },
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "empty object is valid",
|
||||
"data": {},
|
||||
"valid": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -8,7 +8,11 @@ describe('boolean schemas', function() {
|
|||
var ajvs;
|
||||
|
||||
before(function() {
|
||||
ajvs = [ new Ajv, new Ajv({allErrors: true}) ];
|
||||
ajvs = [
|
||||
new Ajv,
|
||||
new Ajv({allErrors: true}),
|
||||
new Ajv({inlineRefs: false})
|
||||
];
|
||||
});
|
||||
|
||||
describe('top level schema', function() {
|
||||
|
@ -431,6 +435,35 @@ describe('boolean schemas', function() {
|
|||
});
|
||||
|
||||
|
||||
describe('in $ref', function() {
|
||||
describe('schema = true', function() {
|
||||
it('should be valid with any data', function() {
|
||||
ajvs.forEach(test(true, true));
|
||||
});
|
||||
});
|
||||
|
||||
describe('schema = false', function() {
|
||||
it('should be invalid with any data', function() {
|
||||
ajvs.forEach(test(false, false));
|
||||
});
|
||||
});
|
||||
|
||||
function test(boolSchema, valid) {
|
||||
return function (ajv) {
|
||||
var schema = {
|
||||
$ref: '#/definitions/bool',
|
||||
definitions: {
|
||||
bool: boolSchema
|
||||
}
|
||||
};
|
||||
|
||||
var validate = ajv.compile(schema);
|
||||
testSchema(validate, valid);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function testSchema(validate, valid) {
|
||||
validate(1) .should.equal(valid);
|
||||
validate('foo') .should.equal(valid);
|
||||
|
|
Loading…
Reference in New Issue