You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							175 lines
						
					
					
						
							4.4 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							175 lines
						
					
					
						
							4.4 KiB
						
					
					
				| /** | |
|  * @license | |
|  * Copyright 2016 Google Inc. All Rights Reserved. | |
|  * | |
|  * Licensed under the Apache License, Version 2.0 (the "License"); | |
|  * you may not use this file except in compliance with the License. | |
|  * You may obtain a copy of the License at | |
|  * | |
|  *     http://www.apache.org/licenses/LICENSE-2.0 | |
|  * | |
|  * Unless required by applicable law or agreed to in writing, software | |
|  * distributed under the License is distributed on an "AS IS" BASIS, | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
|  * See the License for the specific language governing permissions and | |
|  * limitations under the License. | |
|  */ | |
| 
 | |
| var Validate = exports; | |
| 
 | |
| function InvalidValueError(message) { | |
|   this.message = message; | |
|   this.name = 'InvalidValueError'; | |
|   Error.captureStackTrace(this, InvalidValueError); | |
| } | |
| InvalidValueError.prototype = Object.create(Error.prototype); | |
| InvalidValueError.prototype.constructor = InvalidValueError; | |
| 
 | |
| InvalidValueError.prepend = function(message, error) { | |
|   if (error instanceof InvalidValueError) { | |
|     return new InvalidValueError(message + ': ' + error.message); | |
|   } | |
|   return error; | |
| }; | |
| 
 | |
| Validate.InvalidValueError = InvalidValueError; | |
| 
 | |
| Validate.acceptAll = function(value) { | |
|   return value; | |
| }; | |
| 
 | |
| Validate.optional = function(validator) { | |
|   return function(value) { | |
|     return (value == undefined) ? value : validator(value); | |
|   }; | |
| }; | |
| 
 | |
| Validate.that = function(predicate, message) { | |
|   return function(value) { | |
|     if (predicate(value)) return value; | |
|     throw new InvalidValueError(message); | |
|   }; | |
| }; | |
| 
 | |
| Validate.number = Validate.that(function(value) { | |
|   return typeof value === 'number'; | |
| }, 'not a number'); | |
| 
 | |
| Validate.string = Validate.that(function(value) { | |
|   return typeof value === 'string'; | |
| }, 'not a string'); | |
| 
 | |
| Validate.object = function(propertyValidators) { | |
|   return function(object) { | |
|     var result = {}; | |
| 
 | |
|     if (!object || typeof object !== 'object') { | |
|       throw new InvalidValueError('not an Object'); | |
|     } | |
| 
 | |
|     // Validate all properties. | |
|     for (key in propertyValidators) { | |
|       var validator = propertyValidators[key]; | |
|       try { | |
|         var valid = validator(object[key]); | |
|       } catch (error) { | |
|         if (key in object) { | |
|           throw InvalidValueError.prepend('in property "' + key + '"', error); | |
|         } else { | |
|           throw new InvalidValueError('missing property "' + key + '"'); | |
|         } | |
|       } | |
|       if (valid !== undefined) { | |
|         result[key] = valid; | |
|       } | |
|     } | |
| 
 | |
|     // Check for unexpected properties. | |
|     for (var key in object) { | |
|       if (!propertyValidators[key]) { | |
|         throw new InvalidValueError('unexpected property "' + key + '"'); | |
|       } | |
|     } | |
| 
 | |
|     return result; | |
|   }; | |
| }; | |
| 
 | |
| Validate.array = function(validator) { | |
|   return function(array) { | |
|     var result = []; | |
| 
 | |
|     if (Object.prototype.toString.call(array) !== '[object Array]') { | |
|       throw new InvalidValueError('not an Array'); | |
|     } | |
| 
 | |
|     for (var i = 0; i < array.length; ++i) { | |
|       try { | |
|         result[i] = validator(array[i]); | |
|       } catch (error) { | |
|         throw InvalidValueError.prepend('at index ' + i, error); | |
|       } | |
|     } | |
| 
 | |
|     return result; | |
|   }; | |
| }; | |
| 
 | |
| Validate.oneOf = function(names) { | |
|   var myObject = {}; | |
|   var quotedNames = []; | |
|   names.forEach(function(name) { | |
|     myObject[name] = true; | |
|     quotedNames.push('"' + name + '"'); | |
|   }); | |
| 
 | |
|   return function(value) { | |
|     if (myObject[value]) return value; | |
|     throw new InvalidValueError('not one of ' + quotedNames.join(', ')); | |
|   }; | |
| }; | |
| 
 | |
| Validate.mutuallyExclusiveProperties = function(names) { | |
|   return function(value) { | |
|     if (!value) return value; | |
| 
 | |
|     var present = []; | |
|     names.forEach(function(name) { | |
|       if (name in value) { | |
|         present.push('"' + name + '"'); | |
|       } | |
|     }); | |
| 
 | |
|     if (present.length > 1) { | |
|       throw new InvalidValueError( | |
|           'cannot specify properties ' | |
|           + present.slice(0, -1).join(', ') | |
|           + ' and ' | |
|           + present.slice(-1) | |
|           + ' together'); | |
|     } | |
| 
 | |
|     return value; | |
|   }; | |
| }; | |
| 
 | |
| Validate.compose = function(validators) { | |
|   return function(value) { | |
|     validators.forEach(function(validate) { | |
|       value = validate(value); | |
|     }); | |
|     return value; | |
|   }; | |
| }; | |
| 
 | |
| Validate.boolean = Validate.compose([ | |
|   Validate.that(function(value) { | |
|     return typeof value === 'boolean'; | |
|   }, 'not a boolean'), | |
|   function(value) { | |
|     // In each API, boolean fields default to false, and the presence of | |
|     // a querystring value indicates true, so we omit the value if | |
|     // explicitly set to false. | |
|     return value ? value : undefined; | |
|   } | |
| ]); |