@sanity/validation
Advanced tools
Comparing version 0.133.0-realtime-block-editor.b0c02255 to 0.133.0-realtime-block-editor.b65ceaaa
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -3,0 +3,0 @@ module.exports = { |
@@ -1,6 +0,6 @@ | ||
'use strict'; | ||
"use strict"; | ||
const inferFromSchemaType = require('./inferFromSchemaType'); | ||
const inferFromSchemaType = require('./inferFromSchemaType'); // Note: Mutates schema. Refactor when @sanity/schema supports middlewares | ||
// Note: Mutates schema. Refactor when @sanity/schema supports middlewares | ||
function inferFromSchema(schema) { | ||
@@ -7,0 +7,0 @@ const typeNames = schema.getTypeNames(); |
@@ -1,15 +0,12 @@ | ||
'use strict'; | ||
"use strict"; | ||
const Rule = require('./Rule'); | ||
var _require = require('./validators/slugValidator'); | ||
const _require = require('./validators/slugValidator'), | ||
slugValidator = _require.slugValidator; | ||
const slugValidator = _require.slugValidator; | ||
const _require2 = require('./validators/blockValidator'), | ||
blockValidator = _require2.blockValidator; // eslint-disable-next-line complexity | ||
var _require2 = require('./validators/blockValidator'); | ||
const blockValidator = _require2.blockValidator; | ||
// eslint-disable-next-line complexity | ||
function inferFromSchemaType(typeDef) { | ||
@@ -16,0 +13,0 @@ if (typeDef.validation === false) { |
194
lib/Rule.js
@@ -1,5 +0,9 @@ | ||
'use strict'; | ||
"use strict"; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
const cloneDeep = require('clone-deep'); | ||
const escapeRegex = require('./util/escapeRegex'); | ||
const validate = require('./validate'); | ||
@@ -12,2 +16,3 @@ | ||
let isRequired = prev._required || next._required; | ||
if (!isRequired) { | ||
@@ -21,11 +26,9 @@ isRequired = prev._required === false || next._required === false ? false : undefined; | ||
class Rule { | ||
constructor() { | ||
this.FIELD_REF = Rule.FIELD_REF; | ||
this.reset(); | ||
} | ||
} // Alias to static method, since we often have access to an _instance_ of a rule but not the actual Rule class | ||
// eslint-disable-next-line class-methods-use-this | ||
// Alias to static method, since we often have access to an _instance_ of a rule but not the actual Rule class | ||
// eslint-disable-next-line class-methods-use-this | ||
valueOfField(...args) { | ||
@@ -82,3 +85,2 @@ return Rule.valueOfField(...args); | ||
}); | ||
rule._rules = rule._rules.filter(curr => { | ||
@@ -89,3 +91,2 @@ const disallowDuplicate = isExclusive.includes(curr.flag); | ||
}).concat(rules); | ||
return rule; | ||
@@ -109,7 +110,8 @@ } | ||
return validate(this, value, options); | ||
} | ||
} // Validation flag setters | ||
// Validation flag setters | ||
type(targetType) { | ||
const type = `${targetType.slice(0, 1).toUpperCase()}${targetType.slice(1)}`; | ||
if (!knownTypes.includes(type)) { | ||
@@ -119,3 +121,6 @@ throw new Error(`Unknown type "${targetType}"`); | ||
const rule = this.cloneWithRules([{ flag: 'type', constraint: type }]); | ||
const rule = this.cloneWithRules([{ | ||
flag: 'type', | ||
constraint: type | ||
}]); | ||
rule._type = type; | ||
@@ -126,12 +131,21 @@ return rule; | ||
all(children) { | ||
return this.cloneWithRules([{ flag: 'all', constraint: children }]); | ||
return this.cloneWithRules([{ | ||
flag: 'all', | ||
constraint: children | ||
}]); | ||
} | ||
either(children) { | ||
return this.cloneWithRules([{ flag: 'either', constraint: children }]); | ||
} | ||
return this.cloneWithRules([{ | ||
flag: 'either', | ||
constraint: children | ||
}]); | ||
} // Shared rules | ||
// Shared rules | ||
optional() { | ||
const rule = this.cloneWithRules([{ flag: 'presence', constraint: 'optional' }]); | ||
const rule = this.cloneWithRules([{ | ||
flag: 'presence', | ||
constraint: 'optional' | ||
}]); | ||
rule._required = false; | ||
@@ -142,3 +156,6 @@ return rule; | ||
required() { | ||
const rule = this.cloneWithRules([{ flag: 'presence', constraint: 'required' }]); | ||
const rule = this.cloneWithRules([{ | ||
flag: 'presence', | ||
constraint: 'required' | ||
}]); | ||
rule._required = true; | ||
@@ -149,15 +166,27 @@ return rule; | ||
custom(fn) { | ||
return this.cloneWithRules([{ flag: 'custom', constraint: fn }]); | ||
return this.cloneWithRules([{ | ||
flag: 'custom', | ||
constraint: fn | ||
}]); | ||
} | ||
min(len) { | ||
return this.cloneWithRules([{ flag: 'min', constraint: len }]); | ||
return this.cloneWithRules([{ | ||
flag: 'min', | ||
constraint: len | ||
}]); | ||
} | ||
max(len) { | ||
return this.cloneWithRules([{ flag: 'max', constraint: len }]); | ||
return this.cloneWithRules([{ | ||
flag: 'max', | ||
constraint: len | ||
}]); | ||
} | ||
length(len) { | ||
return this.cloneWithRules([{ flag: 'length', constraint: len }]); | ||
return this.cloneWithRules([{ | ||
flag: 'length', | ||
constraint: len | ||
}]); | ||
} | ||
@@ -167,41 +196,70 @@ | ||
const values = Array.isArray(value) ? value : [value]; | ||
return this.cloneWithRules([{ flag: 'valid', constraint: values }]); | ||
} | ||
return this.cloneWithRules([{ | ||
flag: 'valid', | ||
constraint: values | ||
}]); | ||
} // Numbers only | ||
// Numbers only | ||
integer() { | ||
return this.cloneWithRules([{ flag: 'integer' }]); | ||
return this.cloneWithRules([{ | ||
flag: 'integer' | ||
}]); | ||
} | ||
precision(limit) { | ||
return this.cloneWithRules([{ flag: 'precision', constraint: limit }]); | ||
return this.cloneWithRules([{ | ||
flag: 'precision', | ||
constraint: limit | ||
}]); | ||
} | ||
positive() { | ||
return this.cloneWithRules([{ flag: 'min', constraint: 0 }]); | ||
return this.cloneWithRules([{ | ||
flag: 'min', | ||
constraint: 0 | ||
}]); | ||
} | ||
negative() { | ||
return this.cloneWithRules([{ flag: 'lessThan', constraint: 0 }]); | ||
return this.cloneWithRules([{ | ||
flag: 'lessThan', | ||
constraint: 0 | ||
}]); | ||
} | ||
greaterThan(num) { | ||
return this.cloneWithRules([{ flag: 'greaterThan', constraint: num }]); | ||
return this.cloneWithRules([{ | ||
flag: 'greaterThan', | ||
constraint: num | ||
}]); | ||
} | ||
lessThan(num) { | ||
return this.cloneWithRules([{ flag: 'lessThan', constraint: num }]); | ||
} | ||
return this.cloneWithRules([{ | ||
flag: 'lessThan', | ||
constraint: num | ||
}]); | ||
} // String only | ||
// String only | ||
uppercase() { | ||
return this.cloneWithRules([{ flag: 'stringCasing', constraint: 'uppercase' }]); | ||
return this.cloneWithRules([{ | ||
flag: 'stringCasing', | ||
constraint: 'uppercase' | ||
}]); | ||
} | ||
lowercase() { | ||
return this.cloneWithRules([{ flag: 'stringCasing', constraint: 'lowercase' }]); | ||
return this.cloneWithRules([{ | ||
flag: 'stringCasing', | ||
constraint: 'lowercase' | ||
}]); | ||
} | ||
regex(pattern, name, opts) { | ||
let options = opts || { name }; | ||
let options = opts || { | ||
name | ||
}; | ||
if (!opts && name && (name.name || name.invert)) { | ||
@@ -211,16 +269,28 @@ options = name; | ||
const constraint = Object.assign({}, options, { pattern }); | ||
return this.cloneWithRules([{ flag: 'regex', constraint }]); | ||
const constraint = Object.assign({}, options, { | ||
pattern | ||
}); | ||
return this.cloneWithRules([{ | ||
flag: 'regex', | ||
constraint | ||
}]); | ||
} | ||
email(options) { | ||
return this.cloneWithRules([{ flag: 'email', constraint: options }]); | ||
return this.cloneWithRules([{ | ||
flag: 'email', | ||
constraint: options | ||
}]); | ||
} | ||
uri(opts = {}) { | ||
const options = Object.assign({ scheme: ['http', 'https'], allowRelative: false, relativeOnly: false }, opts); | ||
const options = Object.assign({ | ||
scheme: ['http', 'https'], | ||
allowRelative: false, | ||
relativeOnly: false | ||
}, opts); | ||
const allowedSchemes = Array.isArray(options.scheme) ? options.scheme : [options.scheme]; | ||
options.scheme = allowedSchemes.map(scheme => { | ||
const schemeIsString = typeof scheme === 'string'; | ||
if (!(scheme instanceof RegExp) && schemeIsString === false) { | ||
@@ -237,32 +307,46 @@ throw new Error('scheme must be a RegExp or a String'); | ||
return this.cloneWithRules([{ flag: 'uri', constraint: { options } }]); | ||
} | ||
return this.cloneWithRules([{ | ||
flag: 'uri', | ||
constraint: { | ||
options | ||
} | ||
}]); | ||
} // Array only | ||
// Array only | ||
unique(comparator) { | ||
return this.cloneWithRules([{ flag: 'unique', constraint: comparator }]); | ||
} | ||
return this.cloneWithRules([{ | ||
flag: 'unique', | ||
constraint: comparator | ||
}]); | ||
} // Objects only | ||
// Objects only | ||
reference() { | ||
return this.cloneWithRules([{ flag: 'reference' }]); | ||
return this.cloneWithRules([{ | ||
flag: 'reference' | ||
}]); | ||
} | ||
} | ||
Rule.FIELD_REF = Symbol('FIELD_REF'); | ||
_defineProperty(Rule, "FIELD_REF", Symbol('FIELD_REF')); | ||
Rule.array = () => new Rule().type('Array'); | ||
_defineProperty(Rule, "array", () => new Rule().type('Array')); | ||
Rule.object = () => new Rule().type('Object'); | ||
_defineProperty(Rule, "object", () => new Rule().type('Object')); | ||
Rule.string = () => new Rule().type('String'); | ||
_defineProperty(Rule, "string", () => new Rule().type('String')); | ||
Rule.number = () => new Rule().type('Number'); | ||
_defineProperty(Rule, "number", () => new Rule().type('Number')); | ||
Rule.boolean = () => new Rule().type('Boolean'); | ||
_defineProperty(Rule, "boolean", () => new Rule().type('Boolean')); | ||
Rule.dateTime = () => new Rule().type('Date'); | ||
_defineProperty(Rule, "dateTime", () => new Rule().type('Date')); | ||
Rule.valueOfField = path => ({ type: Rule.FIELD_REF, path }); | ||
_defineProperty(Rule, "valueOfField", path => ({ | ||
type: Rule.FIELD_REF, | ||
path | ||
})); | ||
module.exports = Rule; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -19,2 +19,3 @@ /** | ||
if (a.length != b.length) return false; | ||
for (let i = 0; i < a.length; i++) { | ||
@@ -25,2 +26,3 @@ if (!equal(a[i], b[i])) { | ||
} | ||
return true; | ||
@@ -35,2 +37,3 @@ } | ||
const keys = Object.keys(a); | ||
if (keys.length !== Object.keys(b).length) { | ||
@@ -42,2 +45,3 @@ return false; | ||
const dateB = b instanceof Date; | ||
if (dateA && dateB) { | ||
@@ -53,2 +57,3 @@ return a.getTime() === b.getTime(); | ||
const regexpB = b instanceof RegExp; | ||
if (regexpA && regexpB) { | ||
@@ -55,0 +60,0 @@ return a.toString() == b.toString(); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -3,0 +3,0 @@ /* eslint-disable no-useless-escape */ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,2 +6,3 @@ module.exports = function pathToString(path) { | ||
const segmentType = typeof segment; | ||
if (segmentType === 'number') { | ||
@@ -8,0 +9,0 @@ return `${target}[${segment}]`; |
@@ -1,11 +0,10 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _require = require('lodash'); | ||
const get = _require.get, | ||
const _require = require('lodash'), | ||
get = _require.get, | ||
flatten = _require.flatten; | ||
const ValidationError = require('./ValidationError'); | ||
const genericValidator = require('./validators/genericValidator'); | ||
const promiseLimiter = require('./util/promiseLimiter'); | ||
@@ -23,4 +22,4 @@ const typeValidators = { | ||
let rules = rule._rules; | ||
const valueIsUndefined = value === null || typeof value === 'undefined'; | ||
const valueIsUndefined = value === null || typeof value === 'undefined'; | ||
if (typeof rule._required === 'undefined' && valueIsUndefined) { | ||
@@ -36,12 +35,5 @@ // Run all _custom_ functions if the rule is not set to required or optional | ||
const validators = typeValidators[type] || genericValidator; | ||
const tasks = rules.map(validateRule); | ||
return Promise.all(tasks).then(results => results.filter(Boolean)).then(flatten); // eslint-disable-next-line complexity | ||
const tasks = rules.map(createValidationTask); | ||
return Promise.all(tasks).then(results => results.filter(Boolean)).then(flatten); | ||
function createValidationTask(curr) { | ||
const limiter = options.isChild ? promiseLimiter.children : promiseLimiter.root; | ||
return limiter(() => validateRule(curr)); | ||
} | ||
// eslint-disable-next-line complexity | ||
function validateRule(curr) { | ||
@@ -53,2 +45,3 @@ if (typeof curr.flag === 'undefined') { | ||
const validator = validators[curr.flag]; | ||
if (!validator) { | ||
@@ -60,2 +53,3 @@ const forType = type ? `type "${type}"` : 'rule without declared type'; | ||
let itemConstraint = curr.constraint; | ||
if (itemConstraint && itemConstraint.type === rule.FIELD_REF) { | ||
@@ -79,2 +73,3 @@ if (!options.parent) { | ||
const hasError = result instanceof ValidationError; | ||
if (!hasError) { | ||
@@ -88,8 +83,15 @@ return null; | ||
// Add an item at "root" level (for arrays, the actual array) | ||
results.push({ level: rule._level, item: result }); | ||
} | ||
results.push({ | ||
level: rule._level, | ||
item: result | ||
}); | ||
} // Add individual items for each path | ||
// Add individual items for each path | ||
return results.concat(result.paths.map(path => ({ path, level: rule._level, item: result }))); | ||
return results.concat(result.paths.map(path => ({ | ||
path, | ||
level: rule._level, | ||
item: result | ||
}))); | ||
} | ||
}; |
@@ -1,19 +0,26 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } | ||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
const Type = require('type-of-is'); | ||
var _require = require('lodash'); | ||
const _require = require('lodash'), | ||
flatten = _require.flatten; | ||
const flatten = _require.flatten; | ||
const ValidationError = require('./ValidationError'); | ||
/* eslint-disable no-console */ | ||
/* eslint-disable no-console */ | ||
module.exports = (() => { | ||
module.exports = | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = _asyncToGenerator(function* (doc, schema) { | ||
const documentType = schema.get(doc._type); | ||
if (!documentType) { | ||
@@ -25,6 +32,13 @@ console.warn('Schema type for object type "%s" not found, skipping validation', doc._type); | ||
try { | ||
return yield validateItem(doc, documentType, [], { document: doc }); | ||
return yield validateItem(doc, documentType, [], { | ||
document: doc | ||
}); | ||
} catch (err) { | ||
console.error(err); | ||
return [{ type: 'validation', level: 'error', path: [], item: new ValidationError(err.message) }]; | ||
return [{ | ||
type: 'validation', | ||
level: 'error', | ||
path: [], | ||
item: new ValidationError(err.message) | ||
}]; | ||
} | ||
@@ -36,3 +50,3 @@ }); | ||
}; | ||
})(); | ||
}(); | ||
@@ -56,8 +70,11 @@ function validateItem(item, type, path, options) { | ||
return []; | ||
} | ||
} // Validate actual object itself | ||
// Validate actual object itself | ||
let objChecks = []; | ||
if (type.validation) { | ||
objChecks = type.validation.map((() => { | ||
objChecks = type.validation.map( | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref2 = _asyncToGenerator(function* (rule) { | ||
@@ -70,3 +87,2 @@ const ruleResults = yield rule.validate(obj, { | ||
}); | ||
return applyPath(ruleResults, path); | ||
@@ -78,9 +94,10 @@ }); | ||
}; | ||
})()); | ||
} | ||
}()); | ||
} // Validate fields within object | ||
// Validate fields within object | ||
const fields = type.fields || []; | ||
const fieldChecks = fields.map(field => { | ||
const validation = field.type.validation; | ||
if (!validation) { | ||
@@ -99,3 +116,2 @@ return []; | ||
}); | ||
return Promise.all([...objChecks, ...fieldChecks]).then(flatten); | ||
@@ -107,4 +123,7 @@ } | ||
let arrayChecks = []; | ||
if (type.validation) { | ||
arrayChecks = type.validation.map((() => { | ||
arrayChecks = type.validation.map( | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref3 = _asyncToGenerator(function* (rule) { | ||
@@ -117,3 +136,2 @@ const ruleResults = yield rule.validate(items, { | ||
}); | ||
return applyPath(ruleResults, path); | ||
@@ -125,7 +143,10 @@ }); | ||
}; | ||
})()); | ||
} | ||
// Validate items within array | ||
}()); | ||
} // Validate items within array | ||
const itemChecks = items.map((item, i) => { | ||
const pathSegment = item._key ? { _key: item._key } : i; | ||
const pathSegment = item._key ? { | ||
_key: item._key | ||
} : i; | ||
const itemType = resolveTypeForArrayItem(item, type.of); | ||
@@ -139,3 +160,2 @@ const itemPath = appendPath(path, [pathSegment]); | ||
}); | ||
return Promise.all([...arrayChecks, ...itemChecks]).then(flatten); | ||
@@ -149,4 +169,7 @@ } | ||
const results = type.validation.map(rule => rule.validate(item, { parent: options.parent, document: options.document, path }).then(currRuleResults => applyPath(currRuleResults, path))); | ||
const results = type.validation.map(rule => rule.validate(item, { | ||
parent: options.parent, | ||
document: options.document, | ||
path | ||
}).then(currRuleResults => applyPath(currRuleResults, path))); | ||
return Promise.all(results).then(flatten); | ||
@@ -157,2 +180,3 @@ } | ||
const primitive = !item._type && Type.string(item).toLowerCase(); | ||
if (primitive) { | ||
@@ -172,4 +196,8 @@ return candidates.find(candidate => candidate.jsonType === primitive); | ||
const path = typeof result.path === 'undefined' ? pathPrefix : pathPrefix.concat(result.path); | ||
return _extends({ type: 'validation' }, result, { path }); | ||
return _objectSpread({ | ||
type: 'validation' | ||
}, result, { | ||
path | ||
}); | ||
}); | ||
} |
@@ -1,10 +0,8 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _es6Error = require('es6-error'); | ||
var _es6Error = _interopRequireDefault(require("es6-error")); | ||
var _es6Error2 = _interopRequireDefault(_es6Error); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
class ValidationError extends _es6Error2.default { | ||
class ValidationError extends _es6Error.default { | ||
constructor(message, options = {}) { | ||
@@ -29,4 +27,5 @@ super(message); | ||
} | ||
} | ||
module.exports = ValidationError; |
@@ -1,5 +0,7 @@ | ||
'use strict'; | ||
"use strict"; | ||
const deepEquals = require('../util/deepEquals'); | ||
const ValidationError = require('../ValidationError'); | ||
const genericValidator = require('./genericValidator'); | ||
@@ -41,2 +43,3 @@ | ||
const valueType = typeof values; | ||
if (valueType === 'undefined') { | ||
@@ -47,4 +50,6 @@ return true; | ||
const paths = []; | ||
for (let i = 0; i < values.length; i++) { | ||
const value = values[i]; | ||
if (allowedValues.some(expected => deepEquals(expected, value))) { | ||
@@ -54,7 +59,11 @@ continue; | ||
const pathSegment = value && value._key ? { _key: value._key } : i; | ||
const pathSegment = value && value._key ? { | ||
_key: value._key | ||
} : i; | ||
paths.push([pathSegment]); | ||
} | ||
return paths.length === 0 ? true : new ValidationError(message || 'Value did not match any of allowed values', { paths }); | ||
return paths.length === 0 ? true : new ValidationError(message || 'Value did not match any of allowed values', { | ||
paths | ||
}); | ||
}; | ||
@@ -64,7 +73,9 @@ | ||
const dupeIndices = []; | ||
if (!value) { | ||
return true; | ||
} | ||
/* eslint-disable max-depth */ | ||
/* eslint-disable max-depth */ | ||
for (let x = 0; x < value.length; x++) { | ||
@@ -90,9 +101,13 @@ for (let y = x + 1; y < value.length; y++) { | ||
const paths = dupeIndices.map(idx => { | ||
const item = value[idx]; | ||
const pathSegment = item && item._key ? { _key: item._key } : idx; | ||
const pathSegment = item && item._key ? { | ||
_key: item._key | ||
} : idx; | ||
return [pathSegment]; | ||
}); | ||
return dupeIndices.length > 0 ? new ValidationError(message || `Can't be a duplicate`, { paths }) : true; | ||
return dupeIndices.length > 0 ? new ValidationError(message || `Can't be a duplicate`, { | ||
paths | ||
}) : true; | ||
}; | ||
@@ -99,0 +114,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,41 +6,31 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.blockValidator = void 0; | ||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
const Rule = require('../Rule'); | ||
const ValidationError = require('../ValidationError'); | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
const validateDocument = require('../validateDocument'); | ||
const validateItem = validateDocument.validateItem; | ||
const baseRule = new Rule(); | ||
const _require = require('lodash'), | ||
flatten = _require.flatten; // eslint-disable-next-line import/prefer-default-export | ||
var _require = require('lodash'); | ||
const flatten = _require.flatten; | ||
// eslint-disable-next-line import/prefer-default-export | ||
const blockValidator = exports.blockValidator = (() => { | ||
const blockValidator = | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = _asyncToGenerator(function* (value, options) { | ||
const type = options.type; | ||
const childrenType = type.fields.find(field => field.name === 'children').type; | ||
const spanType = childrenType.of.find(ofType => ofType.name === 'span'); // Validate every markDef (annotation) value | ||
const childrenType = type.fields.find(function (field) { | ||
return field.name === 'children'; | ||
}).type; | ||
const spanType = childrenType.of.find(function (ofType) { | ||
return ofType.name === 'span'; | ||
}); | ||
// Validate every markDef (annotation) value | ||
const activeAnnotationTypes = spanType.annotations.filter(function (annotation) { | ||
return value.markDefs.map(function (def) { | ||
return def._type; | ||
}).includes(annotation.name); | ||
}); | ||
const activeAnnotationTypes = spanType.annotations.filter(annotation => value.markDefs.map(def => def._type).includes(annotation.name)); | ||
const annotationValidations = []; | ||
value.markDefs.forEach(function (markDef) { | ||
const annotationType = activeAnnotationTypes.find(function (aType) { | ||
return aType.name === markDef._type; | ||
}); | ||
const validations = validateItem(markDef, annotationType, ['markDefs', { _key: markDef._key }], { | ||
value.markDefs.forEach(markDef => { | ||
const annotationType = activeAnnotationTypes.find(aType => aType.name === markDef._type); | ||
const validations = validateItem(markDef, annotationType, ['markDefs', { | ||
_key: markDef._key | ||
}], { | ||
parent: value, | ||
@@ -52,4 +42,5 @@ document: options.document | ||
const result = yield Promise.all(annotationValidations).then(flatten); | ||
if (result.length) { | ||
return result.map(function (res) { | ||
return result.map(res => { | ||
res.item.paths = [res.path]; | ||
@@ -59,2 +50,3 @@ return res.item; | ||
} | ||
return true; | ||
@@ -66,2 +58,4 @@ }); | ||
}; | ||
})(); | ||
}(); | ||
exports.blockValidator = blockValidator; |
@@ -1,4 +0,5 @@ | ||
'use strict'; | ||
"use strict"; | ||
const ValidationError = require('../ValidationError'); | ||
const genericValidator = require('./genericValidator'); | ||
@@ -5,0 +6,0 @@ |
@@ -1,4 +0,5 @@ | ||
'use strict'; | ||
"use strict"; | ||
const ValidationError = require('../ValidationError'); | ||
const genericValidator = require('./genericValidator'); | ||
@@ -10,2 +11,3 @@ | ||
const strVal = `${value}`; | ||
if (!strVal || isoDate.test(value)) { | ||
@@ -20,2 +22,3 @@ return true; | ||
const dateVal = value && parseDate(value); | ||
if (!dateVal) { | ||
@@ -34,2 +37,3 @@ return true; // `type()` shoudl catch parse errors | ||
const dateVal = value && parseDate(value); | ||
if (!dateVal) { | ||
@@ -53,2 +57,3 @@ return true; // `type()` shoudl catch parse errors | ||
const isInvalid = isNaN(parsed.getTime()); | ||
if (isInvalid && throwOnError) { | ||
@@ -55,0 +60,0 @@ throw new Error(`Unable to parse "${date}" to a date`); |
@@ -1,13 +0,16 @@ | ||
'use strict'; | ||
"use strict"; | ||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
const Type = require('type-of-is'); | ||
var _require = require('lodash'); | ||
const _require = require('lodash'), | ||
flatten = _require.flatten; | ||
const flatten = _require.flatten; | ||
const deepEquals = require('../util/deepEquals'); | ||
const deepEquals = require('../util/deepEquals'); | ||
const pathToString = require('../util/pathToString'); | ||
const ValidationError = require('../ValidationError'); | ||
@@ -19,2 +22,3 @@ | ||
const actualType = Type.string(value); | ||
if (actualType !== expected && actualType !== 'undefined') { | ||
@@ -38,3 +42,5 @@ return new ValidationError(message || `Expected type "${expected}", got "${actualType}"`); | ||
const items = children.map(child => validate(child, value, { isChild: true })); | ||
const items = children.map(child => validate(child, value, { | ||
isChild: true | ||
})); | ||
return Promise.all(items).then(flatten); | ||
@@ -45,10 +51,15 @@ }; | ||
const numErrors = results.length; | ||
return numErrors === 0 ? true : formatValidationErrors(message, results, { separator: ' - AND - ', operator: 'AND' }); | ||
return numErrors === 0 ? true : formatValidationErrors(message, results, { | ||
separator: ' - AND - ', | ||
operator: 'AND' | ||
}); | ||
}); | ||
const either = (children, value, message) => multiple(children, value).then(results => { | ||
const numErrors = results.length; | ||
const numErrors = results.length; // Read: There is at least one rule that matched | ||
// Read: There is at least one rule that matched | ||
return numErrors < children.length ? true : formatValidationErrors(message, results, { separator: ' - OR - ', operator: 'OR' }); | ||
return numErrors < children.length ? true : formatValidationErrors(message, results, { | ||
separator: ' - OR - ', | ||
operator: 'OR' | ||
}); | ||
}); | ||
@@ -58,2 +69,3 @@ | ||
const valueType = typeof actual; | ||
if (valueType === 'undefined') { | ||
@@ -65,18 +77,17 @@ return true; | ||
const strValue = value && value.length > 30 ? `${value.slice(0, 30)}…` : value; | ||
const defaultMessage = value ? `Value "${strValue}" did not match any of allowed values` : 'Value did not match any of allowed values'; | ||
return allowedValues.some(expected => deepEquals(expected, actual)) ? true : new ValidationError(message || defaultMessage); | ||
}; | ||
const custom = (() => { | ||
const custom = | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = _asyncToGenerator(function* (fn, value, message, options) { | ||
const slowTimer = setTimeout(function () { | ||
const path = pathToString(options.path); | ||
const slowTimer = setTimeout(() => { | ||
const path = pathToString(options.path); // eslint-disable-next-line no-console | ||
// eslint-disable-next-line no-console | ||
console.warn(`Custom validator at ${path} has taken more than ${SLOW_VALIDATOR_TIMEOUT}ms to respond`); | ||
}, SLOW_VALIDATOR_TIMEOUT); | ||
let result; | ||
let result; | ||
try { | ||
@@ -96,2 +107,3 @@ result = yield fn(value, options); | ||
} | ||
return result; | ||
@@ -109,3 +121,5 @@ } | ||
if (result && result.message && result.paths) { | ||
return new ValidationError(message || result.message, { paths: result.paths }); | ||
return new ValidationError(message || result.message, { | ||
paths: result.paths | ||
}); | ||
} | ||
@@ -120,3 +134,3 @@ | ||
}; | ||
})(); | ||
}(); | ||
@@ -128,3 +142,2 @@ function formatValidationErrors(message, results, options = {}) { | ||
}; | ||
return results.length === 1 ? new ValidationError(message || results[0].item.message, errOpts) : new ValidationError(message || `[${results.map(err => err.item.message).join(options.separator)}]`, errOpts); | ||
@@ -131,0 +144,0 @@ } |
@@ -1,4 +0,5 @@ | ||
'use strict'; | ||
"use strict"; | ||
const ValidationError = require('../ValidationError'); | ||
const genericValidator = require('./genericValidator'); | ||
@@ -5,0 +6,0 @@ |
@@ -1,4 +0,5 @@ | ||
'use strict'; | ||
"use strict"; | ||
const ValidationError = require('../ValidationError'); | ||
const genericValidator = require('./genericValidator'); | ||
@@ -24,3 +25,5 @@ | ||
if (typeof value._ref !== 'string') { | ||
return new ValidationError(message || 'Must be a reference to a document', { paths: ['$'] }); | ||
return new ValidationError(message || 'Must be a reference to a document', { | ||
paths: ['$'] | ||
}); | ||
} | ||
@@ -27,0 +30,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,10 +6,11 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.slugValidator = void 0; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } | ||
var _require = require('lodash'); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
const get = _require.get; | ||
const _require = require('lodash'), | ||
get = _require.get; | ||
function getDocumentIds(id) { | ||
@@ -35,8 +36,8 @@ const isDraft = id.indexOf('drafts.') === 0; | ||
const client = require('part:@sanity/base/client'); | ||
const document = options.document, | ||
path = options.path; | ||
var _getDocumentIds = getDocumentIds(document._id); | ||
const published = _getDocumentIds.published, | ||
const _getDocumentIds = getDocumentIds(document._id), | ||
published = _getDocumentIds.published, | ||
draft = _getDocumentIds.draft; | ||
@@ -46,9 +47,12 @@ | ||
const atPath = serializePath(path.concat('current')); | ||
const constraints = ['_type == $docType', `!(_id in [$draft, $published])`, `${atPath} == $slug`].join(' && '); | ||
return client.fetch(`!defined(*[${constraints}][0]._id)`, { docType, draft, published, slug }); | ||
return client.fetch(`!defined(*[${constraints}][0]._id)`, { | ||
docType, | ||
draft, | ||
published, | ||
slug | ||
}); | ||
}; | ||
const slugValidator = exports.slugValidator = (value, options) => { | ||
const slugValidator = (value, options) => { | ||
if (!value) { | ||
@@ -64,3 +68,7 @@ return true; | ||
const isUnique = get(options, 'type.options.isUnique', defaultIsUnique); | ||
return Promise.resolve(isUnique(value.current, _extends({}, options, { defaultIsUnique }))).then(slugIsUnique => slugIsUnique ? true : errorMessage); | ||
}; | ||
return Promise.resolve(isUnique(value.current, _objectSpread({}, options, { | ||
defaultIsUnique | ||
}))).then(slugIsUnique => slugIsUnique ? true : errorMessage); | ||
}; | ||
exports.slugValidator = slugValidator; |
@@ -1,4 +0,5 @@ | ||
'use strict'; | ||
"use strict"; | ||
const ValidationError = require('../ValidationError'); | ||
const genericValidator = require('./genericValidator'); | ||
@@ -8,2 +9,3 @@ | ||
const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; | ||
const isRelativeUrl = url => /^\.*\//.test(url); | ||
@@ -29,2 +31,3 @@ | ||
const strValue = value || ''; | ||
if (strValue.length === wantedLength) { | ||
@@ -35,5 +38,5 @@ return true; | ||
return new ValidationError(message || `Must be exactly ${wantedLength} characters long`); | ||
}; | ||
}; // eslint-disable-next-line complexity | ||
// eslint-disable-next-line complexity | ||
const uri = (constraints, value, message) => { | ||
@@ -44,6 +47,5 @@ const strValue = value || ''; | ||
relativeOnly = options.relativeOnly; | ||
const allowRelative = options.allowRelative || relativeOnly; | ||
let url; | ||
let url; | ||
try { | ||
@@ -71,2 +73,3 @@ // WARNING: Safari checks for a given `base` param by looking at the length of arguments passed | ||
const matchesAllowedScheme = options.scheme.some(scheme => scheme.test(urlScheme)); | ||
if (!matchesAllowedScheme) { | ||
@@ -81,2 +84,3 @@ return new ValidationError(message || 'Does not match allowed protocols/schemes'); | ||
const strValue = value || ''; | ||
if (casing === 'uppercase' && strValue !== strValue.toLocaleUpperCase()) { | ||
@@ -105,9 +109,8 @@ return new ValidationError(message || `Must be all uppercase letters`); | ||
invert = options.invert; | ||
const regName = name || `"${pattern.toString()}"`; | ||
const strValue = value || ''; | ||
const matches = pattern.test(strValue); | ||
if (!invert && !matches || invert && matches) { | ||
const defaultMessage = invert ? `Should not match ${regName}-pattern` : `Does not match ${regName}-pattern`; | ||
return new ValidationError(message || defaultMessage); | ||
@@ -121,2 +124,3 @@ } | ||
const strValue = `${value || ''}`.trim(); | ||
if (!strValue || emailRegex.test(strValue)) { | ||
@@ -123,0 +127,0 @@ return true; |
{ | ||
"name": "@sanity/validation", | ||
"version": "0.133.0-realtime-block-editor.b0c02255", | ||
"version": "0.133.0-realtime-block-editor.b65ceaaa", | ||
"description": "Validation and warning infrastructure for Sanity projects", | ||
@@ -8,3 +8,4 @@ "main": "lib/index.js", | ||
"test": "jest", | ||
"test:watch": "jest --watch" | ||
"test:watch": "jest --watch", | ||
"clean": "rimraf lib" | ||
}, | ||
@@ -33,4 +34,3 @@ "author": "Sanity.io <hello@sanity.io>", | ||
"devDependencies": { | ||
"babel-preset-env": "^1.6.1", | ||
"jest": "^22.1.4" | ||
"jest": "^22.4.3" | ||
}, | ||
@@ -40,3 +40,2 @@ "dependencies": { | ||
"es6-error": "^4.0.2", | ||
"throat": "^4.1.0", | ||
"type-of-is": "^3.5.1" | ||
@@ -43,0 +42,0 @@ }, |
const {get, flatten} = require('lodash') | ||
const ValidationError = require('./ValidationError') | ||
const genericValidator = require('./validators/genericValidator') | ||
const promiseLimiter = require('./util/promiseLimiter') | ||
@@ -30,3 +29,3 @@ const typeValidators = { | ||
const tasks = rules.map(createValidationTask) | ||
const tasks = rules.map(validateRule) | ||
return Promise.all(tasks) | ||
@@ -36,7 +35,2 @@ .then(results => results.filter(Boolean)) | ||
function createValidationTask(curr) { | ||
const limiter = options.isChild ? promiseLimiter.children : promiseLimiter.root | ||
return limiter(() => validateRule(curr)) | ||
} | ||
// eslint-disable-next-line complexity | ||
@@ -43,0 +37,0 @@ function validateRule(curr) { |
@@ -1,6 +0,3 @@ | ||
const Rule = require('../Rule') | ||
const ValidationError = require('../ValidationError') | ||
const validateDocument = require('../validateDocument') | ||
const {validateItem} = validateDocument | ||
const baseRule = new Rule() | ||
const {flatten} = require('lodash') | ||
@@ -7,0 +4,0 @@ |
82344
3
1
2292
42
- Removedthroat@^4.1.0
- Removedthroat@4.1.0(transitive)