283 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			283 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | {{# 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; | ||
|  |   } | ||
|  | }} |