feat: support boolean schemas in $ref
parent
225ef67ce5
commit
f1028c8411
|
@ -209,7 +209,7 @@ function compile(schema, root, localRefs, baseId) {
|
||||||
|
|
||||||
refCode = addLocalRef(ref);
|
refCode = addLocalRef(ref);
|
||||||
var v = resolve.call(self, localCompile, root, ref);
|
var v = resolve.call(self, localCompile, root, ref);
|
||||||
if (!v) {
|
if (v === undefined) {
|
||||||
var localSchema = localRefs && localRefs[ref];
|
var localSchema = localRefs && localRefs[ref];
|
||||||
if (localSchema) {
|
if (localSchema) {
|
||||||
v = resolve.inlineRef(localSchema, opts.inlineRefs)
|
v = resolve.inlineRef(localSchema, opts.inlineRefs)
|
||||||
|
@ -218,7 +218,7 @@ function compile(schema, root, localRefs, baseId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v) {
|
if (v !== undefined) {
|
||||||
replaceLocalRef(ref, v);
|
replaceLocalRef(ref, v);
|
||||||
return resolvedRef(v, refCode);
|
return resolvedRef(v, refCode);
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ function compile(schema, root, localRefs, baseId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolvedRef(refVal, code) {
|
function resolvedRef(refVal, code) {
|
||||||
return typeof refVal == 'object'
|
return typeof refVal == 'object' || typeof refVal == 'boolean'
|
||||||
? { code: code, schema: refVal, inline: true }
|
? { code: code, schema: refVal, inline: true }
|
||||||
: { code: code, $async: refVal && refVal.$async };
|
: { code: code, $async: refVal && refVal.$async };
|
||||||
}
|
}
|
||||||
|
@ -377,7 +377,7 @@ function defaultCode(i) {
|
||||||
|
|
||||||
|
|
||||||
function refValCode(i, refVal) {
|
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) {
|
if (schema instanceof SchemaObject) {
|
||||||
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
|
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
|
||||||
} else if (schema) {
|
} else if (schema !== undefined) {
|
||||||
v = inlineRef(schema, this._opts.inlineRefs)
|
v = inlineRef(schema, this._opts.inlineRefs)
|
||||||
? schema
|
? schema
|
||||||
: compile.call(this, schema, root, undefined, baseId);
|
: compile.call(this, schema, root, undefined, baseId);
|
||||||
|
@ -122,7 +122,7 @@ function getJsonPointer(parsedRef, baseId, schema, root) {
|
||||||
if (part) {
|
if (part) {
|
||||||
part = util.unescapeFragment(part);
|
part = util.unescapeFragment(part);
|
||||||
schema = schema[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.id && !PREVENT_SCOPE_CHANGE[part]) baseId = resolveUrl(baseId, schema.id);
|
||||||
if (schema.$ref) {
|
if (schema.$ref) {
|
||||||
var $ref = resolveUrl(baseId, 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 };
|
return { schema: schema, root: root, baseId: baseId };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module.exports = {
|
||||||
varOccurences: varOccurences,
|
varOccurences: varOccurences,
|
||||||
varReplace: varReplace,
|
varReplace: varReplace,
|
||||||
cleanUpCode: cleanUpCode,
|
cleanUpCode: cleanUpCode,
|
||||||
cleanUpVarErrors: cleanUpVarErrors,
|
finalCleanUpCode: finalCleanUpCode,
|
||||||
schemaHasRules: schemaHasRules,
|
schemaHasRules: schemaHasRules,
|
||||||
schemaHasRulesExcept: schemaHasRulesExcept,
|
schemaHasRulesExcept: schemaHasRulesExcept,
|
||||||
stableStringify: require('json-stable-stringify'),
|
stableStringify: require('json-stable-stringify'),
|
||||||
|
@ -150,16 +150,22 @@ var ERRORS_REGEXP = /[^v\.]errors/g
|
||||||
, RETURN_VALID = 'return errors === 0;'
|
, RETURN_VALID = 'return errors === 0;'
|
||||||
, RETURN_TRUE = 'validate.errors = null; return true;'
|
, RETURN_TRUE = 'validate.errors = null; return true;'
|
||||||
, RETURN_ASYNC = /if \(errors === 0\) return true;\s*else throw new ValidationError\(vErrors\);/
|
, 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);
|
var matches = out.match(ERRORS_REGEXP);
|
||||||
if (!matches || matches.length !== 2) return out;
|
if (!matches || matches.length !== 2) return out;
|
||||||
return async
|
out = async
|
||||||
? out.replace(REMOVE_ERRORS_ASYNC, '')
|
? out.replace(REMOVE_ERRORS_ASYNC, '')
|
||||||
.replace(RETURN_ASYNC, RETURN_TRUE_ASYNC)
|
.replace(RETURN_ASYNC, RETURN_TRUE_ASYNC)
|
||||||
: out.replace(REMOVE_ERRORS, '')
|
: out.replace(REMOVE_ERRORS, '')
|
||||||
.replace(RETURN_VALID, RETURN_TRUE);
|
.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.cleanUp: {{ out = it.util.cleanUpCode(out); }} #}}
|
||||||
|
|
||||||
|
|
||||||
{{## def.cleanUpVarErrors: {{ out = it.util.cleanUpVarErrors(out, $async); }} #}}
|
{{## def.finalCleanUp: {{ out = it.util.finalCleanUpCode(out, $async); }} #}}
|
||||||
|
|
||||||
|
|
||||||
{{## def.$data:
|
{{## def.$data:
|
||||||
|
|
|
@ -43,9 +43,9 @@
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
||||||
{{? typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref) }}
|
{{? typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref) }}
|
||||||
|
{{ var $keyword = 'false schema'; }}
|
||||||
|
{{# def.setupKeyword }}
|
||||||
{{? it.schema === false}}
|
{{? it.schema === false}}
|
||||||
{{ var $keyword = 'false schema'; }}
|
|
||||||
{{# def.setupKeyword }}
|
|
||||||
{{? it.isTop}}
|
{{? it.isTop}}
|
||||||
{{ $breakOnError = true; }}
|
{{ $breakOnError = true; }}
|
||||||
{{??}}
|
{{??}}
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
|
|
||||||
var vErrors = null; {{ /* don't edit, used in replace */ }}
|
var vErrors = null; {{ /* don't edit, used in replace */ }}
|
||||||
var errors = 0; {{ /* 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
|
var $lvl = it.level
|
||||||
|
@ -227,7 +227,7 @@
|
||||||
{{# def.cleanUp }}
|
{{# def.cleanUp }}
|
||||||
|
|
||||||
{{? $top && $breakOnError }}
|
{{? $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;
|
var ajvs;
|
||||||
|
|
||||||
before(function() {
|
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() {
|
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) {
|
function testSchema(validate, valid) {
|
||||||
validate(1) .should.equal(valid);
|
validate(1) .should.equal(valid);
|
||||||
validate('foo') .should.equal(valid);
|
validate('foo') .should.equal(valid);
|
||||||
|
|
Loading…
Reference in New Issue