| {{# def.definitions }} |
| {{# def.errors }} |
| {{# def.defaults }} |
| {{# def.coerce }} |
| |
| {{ /** |
| * schema compilation (render) time: |
| * it = { schema, RULES, _validate, opts } |
| * it.validate - this template function, |
| * it is used recursively to generate code for subschemas |
| * |
| * runtime: |
| * "validate" is a variable name to which this function will be assigned |
| * validateRef etc. are defined in the parent scope in index.js |
| */ }} |
| |
| {{ |
| 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); |
| } |
| } |
| }} |
| |
| {{? it.isTop }} |
| var validate = {{?$async}}{{it.async = true;}}async {{?}}function(data, dataPath, parentData, parentDataProperty, rootData) { |
| 'use strict'; |
| {{? $id && (it.opts.sourceCode || it.opts.processCode) }} |
| {{= '/\*# sourceURL=' + $id + ' */' }} |
| {{?}} |
| {{?}} |
| |
| {{? typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref) }} |
| {{ var $keyword = 'false schema'; }} |
| {{# def.setupKeyword }} |
| {{? it.schema === false}} |
| {{? it.isTop}} |
| {{ $breakOnError = true; }} |
| {{??}} |
| var {{=$valid}} = false; |
| {{?}} |
| {{# def.error:'false schema' }} |
| {{??}} |
| {{? it.isTop}} |
| {{? $async }} |
| return data; |
| {{??}} |
| validate.errors = null; |
| return true; |
| {{?}} |
| {{??}} |
| var {{=$valid}} = true; |
| {{?}} |
| {{?}} |
| |
| {{? it.isTop}} |
| }; |
| return validate; |
| {{?}} |
| |
| {{ return out; }} |
| {{?}} |
| |
| |
| {{? 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 = [undefined]; |
| |
| 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); |
| } |
| }} |
| |
| var vErrors = null; {{ /* don't edit, used in replace */ }} |
| var errors = 0; {{ /* don't edit, used in replace */ }} |
| if (rootData === undefined) rootData = data; {{ /* don't edit, used in replace */ }} |
| {{??}} |
| {{ |
| 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'); |
| }} |
| |
| 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; |
| } |
| }} |
| |
| {{## def.checkType: |
| {{ |
| var $schemaPath = it.schemaPath + '.type' |
| , $errSchemaPath = it.errSchemaPath + '/type' |
| , $method = $typeIsArray ? 'checkDataTypes' : 'checkDataType'; |
| }} |
| |
| if ({{= it.util[$method]($typeSchema, $data, true) }}) { |
| #}} |
| |
| {{? it.schema.$ref && $refKeywords }} |
| {{? it.opts.extendRefs == 'fail' }} |
| {{ throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)'); }} |
| {{?? it.opts.extendRefs !== true }} |
| {{ |
| $refKeywords = false; |
| it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"'); |
| }} |
| {{?}} |
| {{?}} |
| |
| {{? it.schema.$comment && it.opts.$comment }} |
| {{= it.RULES.all.$comment.code(it, '$comment') }} |
| {{?}} |
| |
| {{? $typeSchema }} |
| {{? it.opts.coerceTypes }} |
| {{ var $coerceToTypes = it.util.coerceToTypes(it.opts.coerceTypes, $typeSchema); }} |
| {{?}} |
| |
| {{ var $rulesGroup = it.RULES.types[$typeSchema]; }} |
| {{? $coerceToTypes || $typeIsArray || $rulesGroup === true || |
| ($rulesGroup && !$shouldUseGroup($rulesGroup)) }} |
| {{ |
| var $schemaPath = it.schemaPath + '.type' |
| , $errSchemaPath = it.errSchemaPath + '/type'; |
| }} |
| {{# def.checkType }} |
| {{? $coerceToTypes }} |
| {{# def.coerceType }} |
| {{??}} |
| {{# def.error:'type' }} |
| {{?}} |
| } |
| {{?}} |
| {{?}} |
| |
| |
| {{? it.schema.$ref && !$refKeywords }} |
| {{= it.RULES.all.$ref.code(it, '$ref') }} |
| {{? $breakOnError }} |
| } |
| if (errors === {{?$top}}0{{??}}errs_{{=$lvl}}{{?}}) { |
| {{ $closingBraces2 += '}'; }} |
| {{?}} |
| {{??}} |
| {{~ it.RULES:$rulesGroup }} |
| {{? $shouldUseGroup($rulesGroup) }} |
| {{? $rulesGroup.type }} |
| if ({{= it.util.checkDataType($rulesGroup.type, $data) }}) { |
| {{?}} |
| {{? it.opts.useDefaults }} |
| {{? $rulesGroup.type == 'object' && it.schema.properties }} |
| {{# def.defaultProperties }} |
| {{?? $rulesGroup.type == 'array' && Array.isArray(it.schema.items) }} |
| {{# def.defaultItems }} |
| {{?}} |
| {{?}} |
| {{~ $rulesGroup.rules:$rule }} |
| {{? $shouldUseRule($rule) }} |
| {{ var $code = $rule.code(it, $rule.keyword, $rulesGroup.type); }} |
| {{? $code }} |
| {{= $code }} |
| {{? $breakOnError }} |
| {{ $closingBraces1 += '}'; }} |
| {{?}} |
| {{?}} |
| {{?}} |
| {{~}} |
| {{? $breakOnError }} |
| {{= $closingBraces1 }} |
| {{ $closingBraces1 = ''; }} |
| {{?}} |
| {{? $rulesGroup.type }} |
| } |
| {{? $typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes }} |
| else { |
| {{ |
| var $schemaPath = it.schemaPath + '.type' |
| , $errSchemaPath = it.errSchemaPath + '/type'; |
| }} |
| {{# def.error:'type' }} |
| } |
| {{?}} |
| {{?}} |
| |
| {{? $breakOnError }} |
| if (errors === {{?$top}}0{{??}}errs_{{=$lvl}}{{?}}) { |
| {{ $closingBraces2 += '}'; }} |
| {{?}} |
| {{?}} |
| {{~}} |
| {{?}} |
| |
| {{? $breakOnError }} {{= $closingBraces2 }} {{?}} |
| |
| {{? $top }} |
| {{? $async }} |
| if (errors === 0) return data; {{ /* don't edit, used in replace */ }} |
| else throw new ValidationError(vErrors); {{ /* don't edit, used in replace */ }} |
| {{??}} |
| validate.errors = vErrors; {{ /* don't edit, used in replace */ }} |
| return errors === 0; {{ /* don't edit, used in replace */ }} |
| {{?}} |
| }; |
| |
| return validate; |
| {{??}} |
| var {{=$valid}} = errors === errs_{{=$lvl}}; |
| {{?}} |
| |
| {{# def.cleanUp }} |
| |
| {{? $top }} |
| {{# def.finalCleanUp }} |
| {{?}} |
| |
| {{ |
| 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; |
| } |
| }} |