vue-vuelidate-jsonschema
Version:
Create validation definitions for vuelidate based on json schema
231 lines (191 loc) • 8.83 kB
JavaScript
var additionalItemsValidator = require('./validators/additionalItems')
var additionalPropertiesValidator = require('./validators/additionalProperties')
var anyOfValidator = require('./validators/anyOf')
var betweenValidator = require('./validators/between')
var containsValidator = require('./validators/contains')
var dependenciesValidator = require('./validators/dependencies')
var enumValidator = require('./validators/enum')
var equalValidator = require('./validators/const')
var exclusiveMaxValidator = require('./validators/exclusiveMaximum')
var exclusiveMinValidator = require('./validators/exclusiveMinimum')
var get = require('lodash/get')
var isFunction = require('lodash/isFunction')
var isPlainObject = require('lodash/isPlainObject')
var itemsValidator = require('./validators/items')
var maxItemsValidator = require('./validators/maxItems')
var maxLengthValidator = require('./validators/maxLength')
var maxPropertiesValidator = require('./validators/maxProperties')
var maxValidator = require('./validators/maximum')
var minItemsValidator = require('./validators/minItems')
var minLengthValidator = require('./validators/minLength')
var minPropertiesValidator = require('./validators/minProperties')
var minValidator = require('./validators/minimum')
var multipleOfValidator = require('./validators/multipleOf')
var notValidator = require('./validators/not')
var oneOfValidator = require('./validators/oneOf')
var patternPropertiesValidator = require('./validators/patternProperties')
var patternValidator = require('./validators/pattern')
var propertyNamesValidator = require('./validators/propertyNames')
var reduce = require('lodash/reduce')
var requiredValidator = require('./validators/required')
var typeArrayValidator = require('./validators/typeArray')
var typeValidator = require('./validators/type')
var uniq = require('lodash/uniq')
var uniqueValidator = require('./validators/uniqueItems')
var validators = require('vuelidate/lib/validators')
function mergeIntoArray(to, from) {
var allKeys = uniq(Object.keys(to).concat(Object.keys(from)))
allKeys.forEach(function(key) {
var toVal = to[key]
var fromVal = from[key]
if (to.hasOwnProperty(key) && from.hasOwnProperty(key) && isFunction(fromVal)) {
to[key] = [].concat(toVal).concat(fromVal)
} else if (isPlainObject(toVal) && isPlainObject(fromVal)) {
mergeIntoArray(toVal, fromVal)
} else if (fromVal) {
to[key] = fromVal
}
})
}
function createAndValidator(obj) {
Object.keys(obj).forEach(function(key) {
// TODO: are array valid in a vuelidate validations config? if so we need a different approach
var value = obj[key]
if (Array.isArray(value)) {
obj[key] = validators.and.apply(null, value)
} else if (isPlainObject(value)) {
createAndValidator(value)
}
})
}
function mostBeUndefined(val) {
return val === undefined
}
function getPropertyValidationRules(propertySchema, isRequired, isAttached, propKey, parents) {
var validationObj = {}
var self = this
parents = parents || []
// support for boolean schemas
if (propertySchema === true) {
return validationObj
} else if (propertySchema === false) {
validationObj.schemaNotPresent = mostBeUndefined
return validationObj
}
function has(name) {
return propertySchema.hasOwnProperty(name)
}
// add child properties
if (has('properties')) {
var req = propertySchema.required || []
validationObj = reduce(propertySchema.properties, function(all, childPropSchema, propKey) {
var propRequired = req.indexOf(propKey) !== -1
all[propKey] = getPropertyValidationRules.call(self, childPropSchema, propRequired, isAttached, propKey, parents.concat(propKey))
return all
}, validationObj)
}
if (Array.isArray(propertySchema.type)) {
validationObj.schemaTypes = typeArrayValidator(propertySchema, propertySchema.type.map(function(type) {
return typeValidator(propertySchema, type)
}))
} else if (has('type')) {
validationObj.schemaType = typeValidator(propertySchema, propertySchema.type)
}
if (isRequired) {
validationObj.schemaRequired = requiredValidator(propertySchema, isAttached)
}
if (has('oneOf')) {
validationObj.schemaOneOf = oneOfValidator(propertySchema, propertySchema.oneOf, getPropertyValidationRules)
}
if (has('anyOf')) {
validationObj.schemaAnyOf = anyOfValidator(propertySchema, propertySchema.anyOf, getPropertyValidationRules)
}
if (has('not')) {
validationObj.schemaNot = notValidator(propertySchema, propertySchema.not, getPropertyValidationRules)
}
if (has('additionalItems')) {
validationObj.schemaAdditionalItems = additionalItemsValidator(propertySchema, propertySchema.additionalItems, getPropertyValidationRules)
}
if (has('contains')) {
validationObj.schemaContains = containsValidator(propertySchema, propertySchema.contains, getPropertyValidationRules)
}
if (has('dependencies')) {
validationObj.schemaDependencies = dependenciesValidator(propertySchema, propertySchema.dependencies, getPropertyValidationRules)
}
if (has('minLength')) {
validationObj.schemaMinLength = minLengthValidator(propertySchema, propertySchema.minLength)
}
if (has('maxLength')) {
validationObj.schemaMaxLength = maxLengthValidator(propertySchema, propertySchema.maxLength)
}
if (has('minItems')) {
validationObj.schemaMinItems = minItemsValidator(propertySchema, propertySchema.minItems)
}
if (has('maxItems')) {
validationObj.schemaMaxItems = maxItemsValidator(propertySchema, propertySchema.maxItems)
}
if (has('minimum') && has('maximum')) {
validationObj.schemaBetween = betweenValidator(propertySchema, propertySchema.minimum, propertySchema.maximum)
} else if (has('minimum')) {
validationObj.schemaMinimum = minValidator(propertySchema, propertySchema.minimum)
} else if (has('maximum')) {
validationObj.schemaMaximum = maxValidator(propertySchema, propertySchema.maximum)
}
if (has('exclusiveMinimum')) {
validationObj.schemaExclusiveMinimum = exclusiveMinValidator(propertySchema, propertySchema.exclusiveMinimum)
}
if (has('exclusiveMaximum')) {
validationObj.schemaExclusiveMaximum = exclusiveMaxValidator(propertySchema, propertySchema.exclusiveMaximum)
}
if (has('maxProperties')) {
validationObj.schemaMaxProperties = maxPropertiesValidator(propertySchema, propertySchema.maxProperties)
}
if (has('minProperties')) {
validationObj.schemaMinProperties = minPropertiesValidator(propertySchema, propertySchema.minProperties)
}
if (has('multipleOf')) {
validationObj.schemaMultipleOf = multipleOfValidator(propertySchema, propertySchema.multipleOf)
}
if (has('pattern')) {
validationObj.schemaPattern = patternValidator(propertySchema, new RegExp(propertySchema.pattern))
}
if (has('patternProperties')) {
validationObj.schemaPatternProperties = patternPropertiesValidator(propertySchema, propertySchema.patternProperties, getPropertyValidationRules)
}
if (has('propertyNames')) {
validationObj.schemaPropertyNames = propertyNamesValidator(propertySchema, propertySchema.propertyNames, getPropertyValidationRules)
}
if (has('additionalProperties')) {
validationObj.schemaAdditionalProperties = additionalPropertiesValidator(propertySchema, propertySchema.additionalProperties, getPropertyValidationRules)
}
if (has('enum')) {
validationObj.schemaEnum = enumValidator(propertySchema, propertySchema.enum)
}
if (has('const')) {
validationObj.schemaConst = equalValidator(propertySchema, propertySchema.const)
}
if (has('uniqueItems')) {
validationObj.schemaUniqueItems = uniqueValidator(propertySchema)
}
// if we have a singular type of array then we don't need the dynamic regeneration
if (has('items') && propertySchema.type === 'array' && isPlainObject(propertySchema.items)) {
validationObj.$each = getPropertyValidationRules(propertySchema.items, true, true, null, parents.concat(0))
} else if (has('items') && isPlainObject(propertySchema.items)) {
// A bit costly maybe but regenerate validations if the property is not an array anymore
if (Array.isArray(get(this, parents.join('.')))) {
validationObj.$each = getPropertyValidationRules(propertySchema.items, true, true, null, parents.concat(0))
}
} else if (has('items')) {
validationObj.schemaItems = itemsValidator(propertySchema, getPropertyValidationRules)
}
if (has('allOf')) {
propertySchema.allOf.forEach(function(schema) {
mergeIntoArray(validationObj, getPropertyValidationRules(schema, false, isAttached))
})
createAndValidator(validationObj)
}
return validationObj
}
module.exports = {
getPropertyValidationRules: getPropertyValidationRules
}