Last active
December 11, 2016 00:16
-
-
Save jeff-kilbride/68fea43614235bf7ff9ebb9be804e070 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* checkParams tests the params object against the required object. | |
* The required object can take the following forms: | |
* | |
* { paramName: true } | |
* | |
* paramName in params is ONLY tested for existence. | |
* | |
* { | |
* paramName: { | |
* value: requiredValue | RegExp, | |
* type: requiredType, | |
* cast: true | 'return' | |
* } | |
* } | |
* | |
* If value is provided, paramName is tested for strict equality with requiredValue. The | |
* requiredValue may also be a regular expression object, in which case paramName must | |
* be a string and must pass the RegExp.test() method. | |
* | |
* If type is provided, paramName must match requiredType or, if cast is also provided, | |
* be castable to requiredType. If cast is set to 'return' and paramName is successfully | |
* cast to requiredType, the value in the params object will reflect the requiredType. | |
* Valid requiredType values are string, number, boolean, array, object, function, date, | |
* map, and set. The cast property is only valid with string, number, boolean, and | |
* array types. For all other types, it is ignored. | |
* | |
* If an error occurs, checkParams will throw the appropriate CustomError. If no error | |
* occurs, there is no explicit return value. | |
* | |
* @param {Object} params | |
* @param {Object} required | |
* @throws CustomError | |
*/ | |
function checkParams(params, required) { | |
// Ahem... make sure checkParams gets valid params... | |
if (!params) | |
throw this.MPError.get('params'); | |
else if (!_.isPlainObject(params)) | |
throw this.IPError.get(['params', params]); | |
else if (!required) | |
throw this.MPError.get('required'); | |
else if (!_.isPlainObject(required)) | |
throw this.IPError.get(['required', required]); | |
const names = Object.keys(required); | |
for (let name of names) { | |
const param = params[name]; | |
// Doesn't exist, throw a missing param error. | |
if (param == undefined) | |
throw this.MPError.get(name); | |
// If required[name] is boolean true (not an object), we're done. | |
if (required[name] === true) continue; | |
// Doesn't match required value, throw invalid param error. | |
const rVal = required[name].value; | |
if (rVal && _.isRegExp(rVal)) { | |
if (!_.isString(param) || !rVal.test(param)) | |
throw this.IPError.get([name, param]); | |
} | |
else if (rVal && param !== required[name].value) | |
throw this.IPError.get([name, param]); | |
// Doesn't match required type, throw invalid param error. | |
if (required[name].type) { | |
const cast = required[name].cast; | |
let err = false, test, value; | |
switch (required[name].type) { | |
case 'string': | |
test = _.isString(param); | |
if (cast && !test) | |
value = String(param); | |
else if (!test) | |
err = true; | |
break; | |
case 'number': | |
test = _.isNumber(param); | |
if (cast && !test) | |
value = Number(param); | |
else if (!test) | |
err = true; | |
break; | |
case 'boolean': | |
test = _.isBoolean(param); | |
if (cast && !test) | |
value = Boolean(param); | |
else if (!test) | |
err = true; | |
break; | |
case 'array': | |
test = Array.isArray(param); | |
if (cast && !test) { | |
value = Array.from(param); | |
if (!value.length) err = true; | |
} | |
else if (!test) { | |
err = true; | |
} | |
break; | |
case 'object': | |
if (!_.isPlainObject(param)) | |
err = true; | |
break; | |
case 'function': | |
if (!_.isFunction(param)) | |
err = true; | |
break; | |
case 'date': | |
if (!_.isDate(param)) | |
err = true; | |
break; | |
case 'map': | |
if (!(param instanceof Map)) | |
err = true; | |
break; | |
case 'set': | |
if (!(param instanceof Set)) | |
err = true; | |
break; | |
} | |
// Handle errors and values that couldn't be cast first. | |
if (err || (cast && !value && value !== false)) | |
throw this.IPError.get([name, param]); | |
// Set the newly cast value in the params object, if requested. | |
else if (cast === 'return' && (value || value === false)) | |
params[name] = value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment