@aws-cdk/cloud-assembly-schema
Advanced tools
Comparing version 1.69.0 to 1.70.0
@@ -19,5 +19,5 @@ 'use strict'; | ||
// arguments to other properties | ||
'exclusiveMinimum': true, | ||
'exclusiveMaximum': true, | ||
'additionalItems': true, | ||
'then': true, | ||
'else': true, | ||
// special-handled properties | ||
@@ -51,3 +51,5 @@ '$schema': true, | ||
var list = types.map(function (v) { | ||
return v.id && ('<' + v.id + '>') || (v+''); | ||
if(!v) return; | ||
var id = v.$id || v.id; | ||
return id ? ('<' + id + '>') : (v+''); | ||
}); | ||
@@ -65,5 +67,8 @@ result.addError({ | ||
var throwError = options.throwError; | ||
var throwAll = options.throwAll; | ||
options.throwError = false; | ||
options.throwAll = false; | ||
var res = this.validateSchema(instance, schema, options, ctx); | ||
options.throwError = throwError; | ||
options.throwAll = throwAll; | ||
@@ -99,3 +104,5 @@ if (!res.valid && callback instanceof Function) { | ||
var list = schema.anyOf.map(function (v, i) { | ||
return (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
var id = v.$id || v.id; | ||
if(id) return '<' + id + '>'; | ||
return(v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
}); | ||
@@ -135,3 +142,4 @@ if (options.nestedErrors) { | ||
if(!valid.valid){ | ||
var msg = (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
var id = v.$id || v.id; | ||
var msg = id || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
result.addError({ | ||
@@ -171,3 +179,4 @@ name: 'allOf', | ||
var list = schema.oneOf.map(function (v, i) { | ||
return (v.id && ('<' + v.id + '>')) || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
var id = v.$id || v.id; | ||
return id || (v.title && JSON.stringify(v.title)) || (v['$ref'] && ('<' + v['$ref'] + '>')) || '[subschema '+i+']'; | ||
}); | ||
@@ -187,2 +196,31 @@ if (count!==1) { | ||
/** | ||
* Validates "then" or "else" depending on the result of validating "if" | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param ctx | ||
* @return {String|null} | ||
*/ | ||
validators.if = function validateIf (instance, schema, options, ctx) { | ||
// Ignore undefined instances | ||
if (instance === undefined) return null; | ||
if (!helpers.isSchema(schema.if)) throw new Error('Expected "if" keyword to be a schema'); | ||
var ifValid = testSchemaNoThrow.call(this, instance, options, ctx, null, schema.if); | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var res; | ||
if(ifValid){ | ||
if (schema.then === undefined) return; | ||
if (!helpers.isSchema(schema.then)) throw new Error('Expected "then" keyword to be a schema'); | ||
res = this.validateSchema(instance, schema.then, options, ctx.makeChild(schema.then)); | ||
result.importErrors(res); | ||
}else{ | ||
if (schema.else === undefined) return; | ||
if (!helpers.isSchema(schema.else)) throw new Error('Expected "else" keyword to be a schema'); | ||
res = this.validateSchema(instance, schema.else, options, ctx.makeChild(schema.else)); | ||
result.importErrors(res); | ||
} | ||
return result; | ||
}; | ||
function getEnumerableProperty(object, key){ | ||
@@ -194,3 +232,3 @@ // Determine if `key` shows up in `for(var key in object)` | ||
if(!(key in object)) return; | ||
while(object = Object.getPrototypeOf(object)){ | ||
while( (object = Object.getPrototypeOf(object)) ){ | ||
if(Object.propertyIsEnumerable.call(object, key)) return object[key]; | ||
@@ -201,2 +239,26 @@ } | ||
/** | ||
* Validates propertyNames | ||
* @param instance | ||
* @param schema | ||
* @param options | ||
* @param ctx | ||
* @return {String|null|ValidatorResult} | ||
*/ | ||
validators.propertyNames = function validatePropertyNames (instance, schema, options, ctx) { | ||
if(!this.types.object(instance)) return; | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var subschema = schema.propertyNames!==undefined ? schema.propertyNames : {}; | ||
if(!helpers.isSchema(subschema)) throw new SchemaError('Expected "propertyNames" to be a schema (object or boolean)'); | ||
for (var property in instance) { | ||
if(getEnumerableProperty(instance, property) !== undefined){ | ||
var res = this.validateSchema(property, subschema, options, ctx.makeChild(subschema)); | ||
result.importErrors(res); | ||
} | ||
} | ||
return result; | ||
}; | ||
/** | ||
* Validates properties | ||
@@ -214,7 +276,13 @@ * @param instance | ||
for (var property in properties) { | ||
var subschema = properties[property]; | ||
if(subschema===undefined){ | ||
continue; | ||
}else if(subschema===null){ | ||
throw new SchemaError('Unexpected null, expected schema in "properties"'); | ||
} | ||
if (typeof options.preValidateProperty == 'function') { | ||
options.preValidateProperty(instance, property, properties[property], options, ctx); | ||
options.preValidateProperty(instance, property, subschema, options, ctx); | ||
} | ||
var prop = getEnumerableProperty(instance, property); | ||
var res = this.validateSchema(prop, properties[property], options, ctx.makeChild(properties[property], property)); | ||
var res = this.validateSchema(prop, subschema, options, ctx.makeChild(subschema, property)); | ||
if(res.instance !== result.instance[property]) result.instance[property] = res.instance; | ||
@@ -242,3 +310,3 @@ result.importErrors(res); | ||
argument: property, | ||
message: "additionalProperty " + JSON.stringify(property) + " exists in instance when not allowed", | ||
message: "is not allowed to have the additional property " + JSON.stringify(property), | ||
}); | ||
@@ -274,2 +342,8 @@ } else { | ||
for (var pattern in patternProperties) { | ||
var subschema = patternProperties[pattern]; | ||
if(subschema===undefined){ | ||
continue; | ||
}else if(subschema===null){ | ||
throw new SchemaError('Unexpected null, expected schema in "patternProperties"'); | ||
} | ||
try { | ||
@@ -288,6 +362,6 @@ var regexp = new RegExp(pattern, 'u'); | ||
if (typeof options.preValidateProperty == 'function') { | ||
options.preValidateProperty(instance, property, patternProperties[pattern], options, ctx); | ||
options.preValidateProperty(instance, property, subschema, options, ctx); | ||
} | ||
var res = this.validateSchema(instance[property], patternProperties[pattern], options, ctx.makeChild(patternProperties[pattern], property)); | ||
var res = this.validateSchema(instance[property], subschema, options, ctx.makeChild(subschema, property)); | ||
if(res.instance !== result.instance[property]) result.instance[property] = res.instance; | ||
@@ -407,15 +481,19 @@ result.importErrors(res); | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var valid = true; | ||
if (schema.exclusiveMinimum && schema.exclusiveMinimum === true) { | ||
valid = instance > schema.minimum; | ||
if(!(instance > schema.minimum)){ | ||
result.addError({ | ||
name: 'minimum', | ||
argument: schema.minimum, | ||
message: "must be greater than " + schema.minimum, | ||
}); | ||
} | ||
} else { | ||
valid = instance >= schema.minimum; | ||
if(!(instance >= schema.minimum)){ | ||
result.addError({ | ||
name: 'minimum', | ||
argument: schema.minimum, | ||
message: "must be greater than or equal to " + schema.minimum, | ||
}); | ||
} | ||
} | ||
if (!valid) { | ||
result.addError({ | ||
name: 'minimum', | ||
argument: schema.minimum, | ||
message: "must have a minimum value of " + schema.minimum, | ||
}); | ||
} | ||
return result; | ||
@@ -433,13 +511,39 @@ }; | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var valid; | ||
if (schema.exclusiveMaximum && schema.exclusiveMaximum === true) { | ||
valid = instance < schema.maximum; | ||
if(!(instance < schema.maximum)){ | ||
result.addError({ | ||
name: 'maximum', | ||
argument: schema.maximum, | ||
message: "must be less than " + schema.maximum, | ||
}); | ||
} | ||
} else { | ||
valid = instance <= schema.maximum; | ||
if(!(instance <= schema.maximum)){ | ||
result.addError({ | ||
name: 'maximum', | ||
argument: schema.maximum, | ||
message: "must be less than or equal to " + schema.maximum, | ||
}); | ||
} | ||
} | ||
return result; | ||
}; | ||
/** | ||
* Validates the number form of exclusiveMinimum when the type of the instance value is a number. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.exclusiveMinimum = function validateExclusiveMinimum (instance, schema, options, ctx) { | ||
// Support the boolean form of exclusiveMinimum, which is handled by the "minimum" keyword. | ||
if(typeof schema.exclusiveMaximum === 'boolean') return; | ||
if (!this.types.number(instance)) return; | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var valid = instance > schema.exclusiveMinimum; | ||
if (!valid) { | ||
result.addError({ | ||
name: 'maximum', | ||
argument: schema.maximum, | ||
message: "must have a maximum value of " + schema.maximum, | ||
name: 'exclusiveMinimum', | ||
argument: schema.exclusiveMinimum, | ||
message: "must be strictly greater than " + schema.exclusiveMinimum, | ||
}); | ||
@@ -451,2 +555,24 @@ } | ||
/** | ||
* Validates the number form of exclusiveMaximum when the type of the instance value is a number. | ||
* @param instance | ||
* @param schema | ||
* @return {String|null} | ||
*/ | ||
validators.exclusiveMaximum = function validateExclusiveMaximum (instance, schema, options, ctx) { | ||
// Support the boolean form of exclusiveMaximum, which is handled by the "maximum" keyword. | ||
if(typeof schema.exclusiveMaximum === 'boolean') return; | ||
if (!this.types.number(instance)) return; | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
var valid = instance < schema.exclusiveMaximum; | ||
if (!valid) { | ||
result.addError({ | ||
name: 'exclusiveMaximum', | ||
argument: schema.exclusiveMaximum, | ||
message: "must be strictly less than " + schema.exclusiveMaximum, | ||
}); | ||
} | ||
return result; | ||
}; | ||
/** | ||
* Perform validation for multipleOf and divisibleBy, which are essentially the same. | ||
@@ -824,3 +950,4 @@ * @param instance | ||
if (self.testType(instance, schema, options, ctx, type)) { | ||
var schemaId = type && type.id && ('<' + type.id + '>') || type; | ||
var id = type && (type.$id || type.id); | ||
var schemaId = id || type; | ||
result.addError({ | ||
@@ -827,0 +954,0 @@ name: 'not', |
@@ -5,5 +5,10 @@ 'use strict'; | ||
var ValidationError = exports.ValidationError = function ValidationError (message, instance, schema, propertyPath, name, argument) { | ||
if (propertyPath) { | ||
this.property = propertyPath; | ||
var ValidationError = exports.ValidationError = function ValidationError (message, instance, schema, path, name, argument) { | ||
if(Array.isArray(path)){ | ||
this.path = path; | ||
this.property = path.reduce(function(sum, item){ | ||
return sum + makeSuffix(item); | ||
}, 'instance'); | ||
}else if(path !== undefined){ | ||
this.property = path; | ||
} | ||
@@ -14,7 +19,4 @@ if (message) { | ||
if (schema) { | ||
if (schema.id) { | ||
this.schema = schema.id; | ||
} else { | ||
this.schema = schema; | ||
} | ||
var id = schema.$id || schema.id; | ||
this.schema = id || schema; | ||
} | ||
@@ -36,5 +38,9 @@ if (instance !== undefined) { | ||
this.schema = schema; | ||
this.options = options; | ||
this.path = ctx.path; | ||
this.propertyPath = ctx.propertyPath; | ||
this.errors = []; | ||
this.throwError = options && options.throwError; | ||
this.throwFirst = options && options.throwFirst; | ||
this.throwAll = options && options.throwAll; | ||
this.disableFormat = options && options.disableFormat === true; | ||
@@ -46,3 +52,3 @@ }; | ||
if (typeof detail == 'string') { | ||
err = new ValidationError(detail, this.instance, this.schema, this.propertyPath); | ||
err = new ValidationError(detail, this.instance, this.schema, this.path); | ||
} else { | ||
@@ -52,9 +58,11 @@ if (!detail) throw new Error('Missing error detail'); | ||
if (!detail.name) throw new Error('Missing validator type'); | ||
err = new ValidationError(detail.message, this.instance, this.schema, this.propertyPath, detail.name, detail.argument); | ||
err = new ValidationError(detail.message, this.instance, this.schema, this.path, detail.name, detail.argument); | ||
} | ||
if (this.throwError) { | ||
this.errors.push(err); | ||
if (this.throwFirst) { | ||
throw new ValidatorResultError(this); | ||
}else if(this.throwError){ | ||
throw err; | ||
} | ||
this.errors.push(err); | ||
return err; | ||
@@ -82,2 +90,16 @@ }; | ||
module.exports.ValidatorResultError = ValidatorResultError; | ||
function ValidatorResultError(result) { | ||
if(Error.captureStackTrace){ | ||
Error.captureStackTrace(this, ValidatorResultError); | ||
} | ||
this.instance = result.instance; | ||
this.schema = result.schema; | ||
this.options = result.options; | ||
this.errors = result.errors; | ||
} | ||
ValidatorResultError.prototype = new Error(); | ||
ValidatorResultError.prototype.constructor = ValidatorResultError; | ||
ValidatorResultError.prototype.name = "Validation Error"; | ||
/** | ||
@@ -100,6 +122,13 @@ * Describes a problem with a Schema which prevents validation of an instance | ||
var SchemaContext = exports.SchemaContext = function SchemaContext (schema, options, propertyPath, base, schemas) { | ||
var SchemaContext = exports.SchemaContext = function SchemaContext (schema, options, path, base, schemas) { | ||
this.schema = schema; | ||
this.options = options; | ||
this.propertyPath = propertyPath; | ||
if(Array.isArray(path)){ | ||
this.path = path; | ||
this.propertyPath = path.reduce(function(sum, item){ | ||
return sum + makeSuffix(item); | ||
}, 'instance'); | ||
}else{ | ||
this.propertyPath = path; | ||
} | ||
this.base = base; | ||
@@ -114,6 +143,7 @@ this.schemas = schemas; | ||
SchemaContext.prototype.makeChild = function makeChild(schema, propertyName){ | ||
var propertyPath = (propertyName===undefined) ? this.propertyPath : this.propertyPath+makeSuffix(propertyName); | ||
var base = uri.resolve(this.base, schema.id||''); | ||
var ctx = new SchemaContext(schema, this.options, propertyPath, base, Object.create(this.schemas)); | ||
if(schema.id && !ctx.schemas[base]){ | ||
var path = (propertyName===undefined) ? this.path : this.path.concat([propertyName]); | ||
var id = schema.$id || schema.id; | ||
var base = uri.resolve(this.base, id||''); | ||
var ctx = new SchemaContext(schema, this.options, path, base, Object.create(this.schemas)); | ||
if(id && !ctx.schemas[base]){ | ||
ctx.schemas[base] = schema; | ||
@@ -132,3 +162,7 @@ } | ||
'ipv6': /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/, | ||
// TODO: A more accurate regular expression for "uri" goes: | ||
// [A-Za-z][+\-.0-9A-Za-z]*:((/(/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?)?)?#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(/(/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])|/?%[0-9A-Fa-f]{2}|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*(#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?|/(/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+(:\d*)?|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?:\d*|\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)?)? | ||
'uri': /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/, | ||
'uri-reference': /^(((([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|([A-Za-z][+\-.0-9A-Za-z]*:?)?)|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?)?))#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(([A-Za-z][+\-.0-9A-Za-z]*)?%[0-9A-Fa-f]{2}|[!$&-.0-9;=@_~]|[A-Za-z][+\-.0-9A-Za-z]*[!$&-*,;=@_~])(%[0-9A-Fa-f]{2}|[!$&-.0-9;=@-Z_a-z~])*((([/?](%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?#|[/?])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?|([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+(:\d*)?|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?:\d*|\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)?|[A-Za-z][+\-.0-9A-Za-z]*:?)?$/, | ||
@@ -336,1 +370,5 @@ 'color': /^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/, | ||
exports.isSchema = function isSchema(val){ | ||
return (typeof val === 'object' && val) || (typeof val === 'boolean'); | ||
}; | ||
@@ -32,2 +32,3 @@ /* | ||
constructor(message?: string, instance?: any, schema?: Schema, propertyPath?: any, name?: string, argument?: any); | ||
path: (string|number)[]; | ||
property: string; | ||
@@ -52,2 +53,3 @@ message: string; | ||
export interface Schema { | ||
$id?: string | ||
id?: string | ||
@@ -60,5 +62,5 @@ $schema?: string | ||
maximum?: number | ||
exclusiveMaximum?: boolean | ||
exclusiveMaximum?: number | boolean | ||
minimum?: number | ||
exclusiveMinimum?: boolean | ||
exclusiveMinimum?: number | boolean | ||
maxLength?: number | ||
@@ -88,3 +90,3 @@ minLength?: number | ||
} | ||
const?: any[] | ||
const?: any | ||
'enum'?: any[] | ||
@@ -97,2 +99,5 @@ type?: string | string[] | ||
not?: Schema | ||
if?: Schema | ||
then?: Schema | ||
else?: Schema | ||
} | ||
@@ -105,5 +110,6 @@ | ||
rewrite?: RewriteFunction; | ||
propertyName?: string; | ||
base?: string; | ||
throwError?: boolean; | ||
throwFirst?: boolean; | ||
throwAll?: boolean; | ||
nestedErrors?: boolean; | ||
@@ -110,0 +116,0 @@ } |
@@ -6,2 +6,3 @@ 'use strict'; | ||
module.exports.ValidatorResult = require('./helpers').ValidatorResult; | ||
module.exports.ValidatorResultError = require('./helpers').ValidatorResultError; | ||
module.exports.ValidationError = require('./helpers').ValidationError; | ||
@@ -8,0 +9,0 @@ module.exports.SchemaError = require('./helpers').SchemaError; |
@@ -27,3 +27,4 @@ "use strict"; | ||
} | ||
var ourBase = schema.id ? urilib.resolve(baseuri, schema.id) : baseuri; | ||
var id = schema.$id || schema.id; | ||
var ourBase = id ? urilib.resolve(baseuri, id) : baseuri; | ||
if (ourBase) { | ||
@@ -30,0 +31,0 @@ // If there's no fragment, append an empty one |
@@ -9,2 +9,3 @@ 'use strict'; | ||
var ValidatorResult = helpers.ValidatorResult; | ||
var ValidatorResultError = helpers.ValidatorResultError; | ||
var SchemaError = helpers.SchemaError; | ||
@@ -53,3 +54,3 @@ var SchemaContext = helpers.SchemaContext; | ||
var scan = scanSchema(base||anonymousBase, schema); | ||
var ourUri = base || schema.id; | ||
var ourUri = base || schema.$id || schema.id; | ||
for(var uri in scan.id){ | ||
@@ -59,4 +60,6 @@ this.schemas[uri] = scan.id[uri]; | ||
for(var uri in scan.ref){ | ||
// If this schema is already defined, it will be filtered out by the next step | ||
this.unresolvedRefs.push(uri); | ||
} | ||
// Remove newly defined schemas from unresolvedRefs | ||
this.unresolvedRefs = this.unresolvedRefs.filter(function(uri){ | ||
@@ -115,7 +118,8 @@ return typeof self.schemas[uri]==='undefined'; | ||
} | ||
var propertyName = options.propertyName || 'instance'; | ||
// This section indexes subschemas in the provided schema, so they don't need to be added with Validator#addSchema | ||
// This will work so long as the function at uri.resolve() will resolve a relative URI to a relative URI | ||
var base = urilib.resolve(options.base||anonymousBase, schema.id||''); | ||
var id = schema.$id || schema.id; | ||
var base = urilib.resolve(options.base||anonymousBase, id||''); | ||
if(!ctx){ | ||
ctx = new SchemaContext(schema, options, propertyName, base, Object.create(this.schemas)); | ||
ctx = new SchemaContext(schema, options, [], base, Object.create(this.schemas)); | ||
if (!ctx.schemas[base]) { | ||
@@ -130,5 +134,12 @@ ctx.schemas[base] = schema; | ||
} | ||
if(options.required && instance===undefined){ | ||
var result = new ValidatorResult(instance, schema, options, ctx); | ||
result.addError('is required, but is undefined'); | ||
return result; | ||
} | ||
var result = this.validateSchema(instance, schema, options, ctx); | ||
if (!result) { | ||
throw new Error('Result undefined'); | ||
}else if(options.throwAll && result.errors.length){ | ||
throw new ValidatorResultError(result); | ||
} | ||
@@ -191,3 +202,3 @@ return result; | ||
var resolved = this.resolve(schema, switchSchema, ctx); | ||
var subctx = new SchemaContext(resolved.subschema, options, ctx.propertyPath, resolved.switchSchema, ctx.schemas); | ||
var subctx = new SchemaContext(resolved.subschema, options, ctx.path, resolved.switchSchema, ctx.schemas); | ||
return this.validateSchema(instance, resolved.subschema, options, subctx); | ||
@@ -284,2 +295,7 @@ } | ||
Validator.prototype.testType = function validateType (instance, schema, options, ctx, type) { | ||
if(type===undefined){ | ||
return; | ||
}else if(type===null){ | ||
throw new SchemaError('Unexpected null in "type" keyword'); | ||
} | ||
if (typeof this.types[type] == 'function') { | ||
@@ -286,0 +302,0 @@ return this.types[type].call(this, instance); |
{ | ||
"author": "Tom de Grunt <tom@degrunt.nl>", | ||
"name": "jsonschema", | ||
"version": "1.2.10", | ||
"version": "1.4.0", | ||
"license": "MIT", | ||
@@ -12,5 +12,7 @@ "dependencies": {}, | ||
], | ||
"main": "./lib", | ||
"main": "./lib/index.js", | ||
"typings": "./lib/index.d.ts", | ||
"devDependencies": { | ||
"@stryker-mutator/core": "^4.0.0", | ||
"@stryker-mutator/mocha-runner": "^4.0.0", | ||
"chai": "~4.2.0", | ||
@@ -38,4 +40,5 @@ "eslint": "^7.7.0", | ||
"scripts": { | ||
"stryker": "stryker run", | ||
"test": "./node_modules/.bin/mocha -R spec" | ||
} | ||
} |
@@ -110,2 +110,18 @@ [![Build Status](https://secure.travis-ci.org/tdegrunt/jsonschema.svg)](http://travis-ci.org/tdegrunt/jsonschema) | ||
### Handling `undefined` | ||
`undefined` is not a value known to JSON, and by default, the validator treats it as if it is not invalid. i.e., it will return valid. | ||
```javascript | ||
var res = validate(undefined, {type: 'string'}); | ||
res.valid // true | ||
``` | ||
This behavior may be changed with the "required" option: | ||
```javascript | ||
var res = validate(undefined, {type: 'string'}, {required: true}); | ||
res.valid // false | ||
``` | ||
### Formats | ||
@@ -148,5 +164,13 @@ | ||
The first error found will be thrown as an `Error` object if `options.throwError` is `true`. Otherwise all results will be appended to the `result.errors` array. Each item in this array is a `ValidationError` with the following properties: | ||
By default, results will be returned in a `ValidatorResult` object with the following properties: | ||
* property: string. Describes the property path. Starts with `instance` (this is configurable with the `options.propertyName` option), and is delimited with a dot (`.`). | ||
* `instance`: any. | ||
* `schema`: Schema. | ||
* `errors`: ValidationError[]. | ||
* `valid`: boolean. | ||
Each item in `errors` is a `ValidationError` with the following properties: | ||
* path: array. An array of property keys or array offsets, indicating where inside objects or arrays the instance was found. | ||
* property: string. Describes the property path. Starts with `instance`, and is delimited with a dot (`.`). | ||
* message: string. A human-readable message for debugging use. Provided in English and subject to change. | ||
@@ -158,2 +182,12 @@ * schema: object. The schema containing the keyword that failed | ||
The validator can be configured to throw in the event of a validation error: | ||
* If the `throwFirst` option is set, the validator will terminate validation at the first encountered error and throw a `ValidatorResultError` object. | ||
* If the `throwAll` option is set, the validator will throw a `ValidatorResultError` object after the entire instance has been validated. | ||
* If the `throwError` option is set, it will throw at the first encountered validation error (like `throwFirst`), but the `ValidationError` object itself will be thrown. Note that, despite the name, this does not inherit from Error like `ValidatorResultError` does. | ||
The `ValidatorResultError` object has the same properties as `ValidatorResult` and additionally inherits from Error. | ||
#### "nestedErrors" option | ||
@@ -163,3 +197,3 @@ | ||
This behavor may be configured with `options.nestedErrors`. If truthy, it will emit all the errors from the subschemas. This option may be useful when troubleshooting validation errors in complex schemas: | ||
This behavior may be configured with `options.nestedErrors`. If truthy, it will emit all the errors from the subschemas. This option may be useful when troubleshooting validation errors in complex schemas: | ||
@@ -194,5 +228,5 @@ ```javascript | ||
### Custom properties | ||
### Custom keywords | ||
Specify your own JSON Schema properties with the validator.attributes property: | ||
Specify your own JSON Schema keywords with the validator.attributes property: | ||
@@ -308,33 +342,24 @@ ```javascript | ||
```javascript | ||
const coercionHook = function (instance, property, schema, options, ctx) { | ||
var value = instance[property]; | ||
// See examples/coercion.js | ||
function preValidateProperty(object, key, schema, options, ctx) { | ||
var value = object[key]; | ||
if (typeof value === 'undefined') return; | ||
// Skip null and undefined | ||
if (value === null || typeof value == 'undefined') { | ||
return; | ||
} | ||
// If the schema declares a type and the property fails type validation. | ||
if (schema.type && this.attributes.type.call(this, instance, schema, options, ctx.makeChild(schema, property))) { | ||
var types = Array.isArray(schema.type) ? schema.type : [schema.type]; | ||
var coerced = undefined; | ||
// Go through the declared types until we find something that we can | ||
// coerce the value into. | ||
for (var i = 0; typeof coerced == 'undefined' && i < types.length; i++) { | ||
// If we support coercion to this type | ||
if (lib.coercions[types[i]]) { | ||
// ...attempt it. | ||
coerced = lib.coercions[types[i]](value); | ||
} | ||
// Test if the schema declares a type, but the type keyword fails validation | ||
if (schema.type && validator.attributes.type.call(validator, value, schema, options, ctx.makeChild(schema, key))) { | ||
// If the type is "number" but the instance is not a number, cast it | ||
if(schema.type==='number' && typeof value!=='number'){ | ||
object[key] = parseFloat(value); | ||
return; | ||
} | ||
// If we got a successful coercion we modify the property of the instance. | ||
if (typeof coerced != 'undefined') { | ||
instance[property] = coerced; | ||
// If the type is "string" but the instance is not a string, cast it | ||
if(schema.type==='string' && typeof value!=='string'){ | ||
object[key] = String(value).toString(); | ||
return; | ||
} | ||
} | ||
}.bind(validator) | ||
}; | ||
// And now, to actually perform validation with the coercion hook! | ||
v.validate(instance, schema, { preValidateProperty: coercionHook }); | ||
v.validate(instance, schema, { preValidateProperty }); | ||
``` | ||
@@ -341,0 +366,0 @@ |
{ | ||
"name": "@aws-cdk/cloud-assembly-schema", | ||
"version": "1.69.0", | ||
"version": "1.70.0", | ||
"description": "Cloud Assembly Schema", | ||
@@ -55,8 +55,8 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"@types/jest": "^26.0.14", | ||
"@types/mock-fs": "^4.10.0", | ||
"cdk-build-tools": "1.69.0", | ||
"jest": "^26.4.2", | ||
"@types/jest": "^26.0.15", | ||
"@types/mock-fs": "^4.13.0", | ||
"cdk-build-tools": "1.70.0", | ||
"jest": "^26.6.0", | ||
"mock-fs": "^4.13.0", | ||
"pkglint": "1.69.0", | ||
"pkglint": "1.70.0", | ||
"typescript-json-schema": "^0.43.0" | ||
@@ -86,3 +86,3 @@ }, | ||
"dependencies": { | ||
"jsonschema": "^1.2.10", | ||
"jsonschema": "^1.4.0", | ||
"semver": "^7.3.2" | ||
@@ -89,0 +89,0 @@ }, |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
386746
5579
Updatedjsonschema@^1.4.0