Skip to content

Commit

Permalink
[validation] Run custom validators on undefined values unless rule is…
Browse files Browse the repository at this point in the history
… set to optional
  • Loading branch information
rexxars committed Mar 16, 2018
1 parent 59d56fb commit a8119ed
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
15 changes: 12 additions & 3 deletions packages/@sanity/validation/src/Rule.js
Expand Up @@ -6,6 +6,15 @@ const createUriRegex = require('./util/createUriRegex')
const knownTypes = ['Object', 'String', 'Number', 'Boolean', 'Array', 'Date']
const isExclusive = ['type', 'uri', 'email']

const mergeRequired = (prev, next) => {
let isRequired = prev._required || next._required
if (!isRequired) {
isRequired = prev._required === false || next._required === false ? false : undefined
}

return isRequired
}

class Rule {
static FIELD_REF = Symbol('FIELD_REF')
static array = () => new Rule().type('Array')
Expand Down Expand Up @@ -46,13 +55,13 @@ class Rule {
this._type = this._type || null
this._rules = (this._rules || []).filter(rule => rule.flag === 'type')
this._message = null
this._required = false
this._required = undefined
this._level = 'error'
return this
}

isRequired() {
return this._required
return this._required === true
}

clone() {
Expand Down Expand Up @@ -95,7 +104,7 @@ class Rule {
const newRule = this.cloneWithRules(rule._rules)
newRule._type = this._type || rule._type
newRule._message = this._message || rule._message
newRule._required = this._required || rule._required
newRule._required = mergeRequired(this, rule)
newRule._level = this._level === 'error' ? rule._level : this._level
return newRule
}
Expand Down
16 changes: 11 additions & 5 deletions packages/@sanity/validation/src/validate.js
Expand Up @@ -13,15 +13,21 @@ const typeValidators = {
}

module.exports = (rule, value, options = {}) => {
const type = rule._type
const validators = typeValidators[type] || genericValidator
let rules = rule._rules

// Short-circuit on optional, empty fields
if (!rule._required && (value === null || typeof value === 'undefined')) {
const valueIsUndefined = value === null || typeof value === 'undefined'
if (typeof rule._required === 'undefined' && valueIsUndefined) {
// Run all _custom_ functions if the rule is not set to required or optional
rules = rules.filter(curr => curr.flag === 'custom')
} else if (!rule._required && valueIsUndefined) {
// Short-circuit on optional, empty fields
return Promise.resolve([])
}

const tasks = rule._rules.map(createValidationTask)
const type = rule._type
const validators = typeValidators[type] || genericValidator

const tasks = rules.map(createValidationTask)
return Promise.all(tasks)
.then(results => results.filter(Boolean))
.then(flatten)
Expand Down

0 comments on commit a8119ed

Please sign in to comment.