Skip to content
Permalink
9bfb9ba527
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
Latest commit c96f843 Sep 14, 2020 History
0 contributors

Users who have contributed to this file

482 lines (479 sloc) 19.5 KB
'use strict';
module.exports = function generate_validate(it, $keyword, $ruleType) {
var out = '';
var $async = it.schema.$async === true,
$refKeywords = it.util.schemaHasRulesExcept(it.schema, it.RULES.all, '$ref'),
$id = it.self._getId(it.schema);
if (it.opts.strictKeywords) {
var $unknownKwd = it.util.schemaUnknownRules(it.schema, it.RULES.keywords);
if ($unknownKwd) {
var $keywordsMsg = 'unknown keyword: ' + $unknownKwd;
if (it.opts.strictKeywords === 'log') it.logger.warn($keywordsMsg);
else throw new Error($keywordsMsg);
}
}
if (it.isTop) {
out += ' var validate = ';
if ($async) {
it.async = true;
out += 'async ';
}
out += 'function(data, dataPath, parentData, parentDataProperty, rootData) { \'use strict\'; ';
if ($id && (it.opts.sourceCode || it.opts.processCode)) {
out += ' ' + ('/\*# sourceURL=' + $id + ' */') + ' ';
}
}
if (typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref)) {
var $keyword = 'false schema';
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
if (it.schema === false) {
if (it.isTop) {
$breakOnError = true;
} else {
out += ' var ' + ($valid) + ' = false; ';
}
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || 'false schema') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'boolean schema is false\' ';
}
if (it.opts.verbose) {
out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
} else {
if (it.isTop) {
if ($async) {
out += ' return data; ';
} else {
out += ' validate.errors = null; return true; ';
}
} else {
out += ' var ' + ($valid) + ' = true; ';
}
}
if (it.isTop) {
out += ' }; return validate; ';
}
return out;
}
if (it.isTop) {
var $top = it.isTop,
$lvl = it.level = 0,
$dataLvl = it.dataLevel = 0,
$data = 'data';
it.rootId = it.resolve.fullPath(it.self._getId(it.root.schema));
it.baseId = it.baseId || it.rootId;
delete it.isTop;
it.dataPathArr = [""];
if (it.schema.default !== undefined && it.opts.useDefaults && it.opts.strictDefaults) {
var $defaultMsg = 'default is ignored in the schema root';
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg);
else throw new Error($defaultMsg);
}
out += ' var vErrors = null; ';
out += ' var errors = 0; ';
out += ' if (rootData === undefined) rootData = data; ';
} else {
var $lvl = it.level,
$dataLvl = it.dataLevel,
$data = 'data' + ($dataLvl || '');
if ($id) it.baseId = it.resolve.url(it.baseId, $id);
if ($async && !it.async) throw new Error('async schema in sync schema');
out += ' var errs_' + ($lvl) + ' = errors;';
}
var $valid = 'valid' + $lvl,
$breakOnError = !it.opts.allErrors,
$closingBraces1 = '',
$closingBraces2 = '';
var $errorKeyword;
var $typeSchema = it.schema.type,
$typeIsArray = Array.isArray($typeSchema);
if ($typeSchema && it.opts.nullable && it.schema.nullable === true) {
if ($typeIsArray) {
if ($typeSchema.indexOf('null') == -1) $typeSchema = $typeSchema.concat('null');
} else if ($typeSchema != 'null') {
$typeSchema = [$typeSchema, 'null'];
$typeIsArray = true;
}
}
if ($typeIsArray && $typeSchema.length == 1) {
$typeSchema = $typeSchema[0];
$typeIsArray = false;
}
if (it.schema.$ref && $refKeywords) {
if (it.opts.extendRefs == 'fail') {
throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)');
} else if (it.opts.extendRefs !== true) {
$refKeywords = false;
it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"');
}
}
if (it.schema.$comment && it.opts.$comment) {
out += ' ' + (it.RULES.all.$comment.code(it, '$comment'));
}
if ($typeSchema) {
if (it.opts.coerceTypes) {
var $coerceToTypes = it.util.coerceToTypes(it.opts.coerceTypes, $typeSchema);
}
var $rulesGroup = it.RULES.types[$typeSchema];
if ($coerceToTypes || $typeIsArray || $rulesGroup === true || ($rulesGroup && !$shouldUseGroup($rulesGroup))) {
var $schemaPath = it.schemaPath + '.type',
$errSchemaPath = it.errSchemaPath + '/type';
var $schemaPath = it.schemaPath + '.type',
$errSchemaPath = it.errSchemaPath + '/type',
$method = $typeIsArray ? 'checkDataTypes' : 'checkDataType';
out += ' if (' + (it.util[$method]($typeSchema, $data, it.opts.strictNumbers, true)) + ') { ';
if ($coerceToTypes) {
var $dataType = 'dataType' + $lvl,
$coerced = 'coerced' + $lvl;
out += ' var ' + ($dataType) + ' = typeof ' + ($data) + '; var ' + ($coerced) + ' = undefined; ';
if (it.opts.coerceTypes == 'array') {
out += ' if (' + ($dataType) + ' == \'object\' && Array.isArray(' + ($data) + ') && ' + ($data) + '.length == 1) { ' + ($data) + ' = ' + ($data) + '[0]; ' + ($dataType) + ' = typeof ' + ($data) + '; if (' + (it.util.checkDataType(it.schema.type, $data, it.opts.strictNumbers)) + ') ' + ($coerced) + ' = ' + ($data) + '; } ';
}
out += ' if (' + ($coerced) + ' !== undefined) ; ';
var arr1 = $coerceToTypes;
if (arr1) {
var $type, $i = -1,
l1 = arr1.length - 1;
while ($i < l1) {
$type = arr1[$i += 1];
if ($type == 'string') {
out += ' else if (' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\') ' + ($coerced) + ' = \'\' + ' + ($data) + '; else if (' + ($data) + ' === null) ' + ($coerced) + ' = \'\'; ';
} else if ($type == 'number' || $type == 'integer') {
out += ' else if (' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' === null || (' + ($dataType) + ' == \'string\' && ' + ($data) + ' && ' + ($data) + ' == +' + ($data) + ' ';
if ($type == 'integer') {
out += ' && !(' + ($data) + ' % 1)';
}
out += ')) ' + ($coerced) + ' = +' + ($data) + '; ';
} else if ($type == 'boolean') {
out += ' else if (' + ($data) + ' === \'false\' || ' + ($data) + ' === 0 || ' + ($data) + ' === null) ' + ($coerced) + ' = false; else if (' + ($data) + ' === \'true\' || ' + ($data) + ' === 1) ' + ($coerced) + ' = true; ';
} else if ($type == 'null') {
out += ' else if (' + ($data) + ' === \'\' || ' + ($data) + ' === 0 || ' + ($data) + ' === false) ' + ($coerced) + ' = null; ';
} else if (it.opts.coerceTypes == 'array' && $type == 'array') {
out += ' else if (' + ($dataType) + ' == \'string\' || ' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' == null) ' + ($coerced) + ' = [' + ($data) + ']; ';
}
}
}
out += ' else { ';
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
out += '' + ($typeSchema);
}
out += '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be ';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
out += '' + ($typeSchema);
}
out += '\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += ' } if (' + ($coerced) + ' !== undefined) { ';
var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData',
$parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty';
out += ' ' + ($data) + ' = ' + ($coerced) + '; ';
if (!$dataLvl) {
out += 'if (' + ($parentData) + ' !== undefined)';
}
out += ' ' + ($parentData) + '[' + ($parentDataProperty) + '] = ' + ($coerced) + '; } ';
} else {
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
out += '' + ($typeSchema);
}
out += '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be ';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
out += '' + ($typeSchema);
}
out += '\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
}
out += ' } ';
}
}
if (it.schema.$ref && !$refKeywords) {
out += ' ' + (it.RULES.all.$ref.code(it, '$ref')) + ' ';
if ($breakOnError) {
out += ' } if (errors === ';
if ($top) {
out += '0';
} else {
out += 'errs_' + ($lvl);
}
out += ') { ';
$closingBraces2 += '}';
}
} else {
var arr2 = it.RULES;
if (arr2) {
var $rulesGroup, i2 = -1,
l2 = arr2.length - 1;
while (i2 < l2) {
$rulesGroup = arr2[i2 += 1];
if ($shouldUseGroup($rulesGroup)) {
if ($rulesGroup.type) {
out += ' if (' + (it.util.checkDataType($rulesGroup.type, $data, it.opts.strictNumbers)) + ') { ';
}
if (it.opts.useDefaults) {
if ($rulesGroup.type == 'object' && it.schema.properties) {
var $schema = it.schema.properties,
$schemaKeys = Object.keys($schema);
var arr3 = $schemaKeys;
if (arr3) {
var $propertyKey, i3 = -1,
l3 = arr3.length - 1;
while (i3 < l3) {
$propertyKey = arr3[i3 += 1];
var $sch = $schema[$propertyKey];
if ($sch.default !== undefined) {
var $passData = $data + it.util.getProperty($propertyKey);
if (it.compositeRule) {
if (it.opts.strictDefaults) {
var $defaultMsg = 'default is ignored for: ' + $passData;
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg);
else throw new Error($defaultMsg);
}
} else {
out += ' if (' + ($passData) + ' === undefined ';
if (it.opts.useDefaults == 'empty') {
out += ' || ' + ($passData) + ' === null || ' + ($passData) + ' === \'\' ';
}
out += ' ) ' + ($passData) + ' = ';
if (it.opts.useDefaults == 'shared') {
out += ' ' + (it.useDefault($sch.default)) + ' ';
} else {
out += ' ' + (JSON.stringify($sch.default)) + ' ';
}
out += '; ';
}
}
}
}
} else if ($rulesGroup.type == 'array' && Array.isArray(it.schema.items)) {
var arr4 = it.schema.items;
if (arr4) {
var $sch, $i = -1,
l4 = arr4.length - 1;
while ($i < l4) {
$sch = arr4[$i += 1];
if ($sch.default !== undefined) {
var $passData = $data + '[' + $i + ']';
if (it.compositeRule) {
if (it.opts.strictDefaults) {
var $defaultMsg = 'default is ignored for: ' + $passData;
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg);
else throw new Error($defaultMsg);
}
} else {
out += ' if (' + ($passData) + ' === undefined ';
if (it.opts.useDefaults == 'empty') {
out += ' || ' + ($passData) + ' === null || ' + ($passData) + ' === \'\' ';
}
out += ' ) ' + ($passData) + ' = ';
if (it.opts.useDefaults == 'shared') {
out += ' ' + (it.useDefault($sch.default)) + ' ';
} else {
out += ' ' + (JSON.stringify($sch.default)) + ' ';
}
out += '; ';
}
}
}
}
}
}
var arr5 = $rulesGroup.rules;
if (arr5) {
var $rule, i5 = -1,
l5 = arr5.length - 1;
while (i5 < l5) {
$rule = arr5[i5 += 1];
if ($shouldUseRule($rule)) {
var $code = $rule.code(it, $rule.keyword, $rulesGroup.type);
if ($code) {
out += ' ' + ($code) + ' ';
if ($breakOnError) {
$closingBraces1 += '}';
}
}
}
}
}
if ($breakOnError) {
out += ' ' + ($closingBraces1) + ' ';
$closingBraces1 = '';
}
if ($rulesGroup.type) {
out += ' } ';
if ($typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes) {
out += ' else { ';
var $schemaPath = it.schemaPath + '.type',
$errSchemaPath = it.errSchemaPath + '/type';
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
out += '' + ($typeSchema);
}
out += '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be ';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
out += '' + ($typeSchema);
}
out += '\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += ' } ';
}
}
if ($breakOnError) {
out += ' if (errors === ';
if ($top) {
out += '0';
} else {
out += 'errs_' + ($lvl);
}
out += ') { ';
$closingBraces2 += '}';
}
}
}
}
}
if ($breakOnError) {
out += ' ' + ($closingBraces2) + ' ';
}
if ($top) {
if ($async) {
out += ' if (errors === 0) return data; ';
out += ' else throw new ValidationError(vErrors); ';
} else {
out += ' validate.errors = vErrors; ';
out += ' return errors === 0; ';
}
out += ' }; return validate;';
} else {
out += ' var ' + ($valid) + ' = errors === errs_' + ($lvl) + ';';
}
function $shouldUseGroup($rulesGroup) {
var rules = $rulesGroup.rules;
for (var i = 0; i < rules.length; i++)
if ($shouldUseRule(rules[i])) return true;
}
function $shouldUseRule($rule) {
return it.schema[$rule.keyword] !== undefined || ($rule.implements && $ruleImplementsSomeKeyword($rule));
}
function $ruleImplementsSomeKeyword($rule) {
var impl = $rule.implements;
for (var i = 0; i < impl.length; i++)
if (it.schema[impl[i]] !== undefined) return true;
}
return out;
}