flexi-validate
Version:
Flexible JavaScript object validator
447 lines (405 loc) • 16.4 kB
JavaScript
var flexiValidate =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isValid = isValid;
exports.isValidAsync = isValidAsync;
exports.messages = messages;
exports.messagesAsync = messagesAsync;
exports.allMessages = allMessages;
exports.allMessagesAsync = allMessagesAsync;
exports.cleanAttributes = cleanAttributes;
/*
Example data structure for a validation object
validationObj = {
validationInput: {
validationProp: {
isValid: function() {
return true;
},
message: function() {
return 'is required';
}
}
},
username: {
required: {
isValid: function(username) {
if(typeof(username) === 'undefined')
return false;
if(username === null)
return false;
if(username.trim().length <= 0)
return false;
return true;
},
message: 'Username is required'
}
}
};
*/
/*
This object has methods for working with a validation
data structure as seen above.
*/
// Reduces an array of booleans with the and
// operation.
// ie. item[0] && item[1] && item[n] ...
// Returns true if all items are true
function functionalAnd(result, current) {
if (result) {
return current;
} else {
return result;
}
}
// Reduces an array of objects with a key and message
// property into a single object
function reduceToObject(result, current) {
result[current.key] = current.message;
return result;
}
// Reduces an array of keys to the resulting object
// ie. result[nestedKey[0]][nestedKey[1]][nestedKey[n]] ...
// Initial value should be the target object
function nestedKeyReduce(result, nestedKey) {
if (typeof result !== 'undefined') {
if (typeof result[nestedKey] !== 'undefined') {
return result[nestedKey];
}
}
return undefined;
}
// Returns a property from a target object using
// a key. If the key is nested it will resolve
// the nesting before returning the object
function resolveNestedObject(targetObj, key) {
var nestedKeys = key.split('.');
var isNestedKey = nestedKeys.length > 1;
var resultObj = undefined;
if (isNestedKey) {
resultObj = nestedKeys.reduce(nestedKeyReduce, targetObj);
} else {
resultObj = targetObj[key];
}
return resultObj;
}
// Returns true if the provided item is not
// null or undefined
function isNotUndefined(item) {
return typeof item !== 'undefined' && item !== null;
}
// Validates parameters
function validateParams(targetObj, validationObj) {
if ((typeof targetObj === 'undefined' ? 'undefined' : _typeof(targetObj)) !== 'object') {
throw new Error('Target object must be an object');
}
if ((typeof validationObj === 'undefined' ? 'undefined' : _typeof(validationObj)) !== 'object') {
throw new Error('Validation object must be an object');
}
}
// Validates inputKey parameter
function validateInputKey(validationObj, inputKey) {
if (typeof inputKey !== 'string') {
throw new Error('Validation input must be a property string');
} else if (typeof validationObj[inputKey] === 'undefined') {
throw new Error('Validation input property must exist on validation object');
}
}
// Returns true if all validations are valid
function isValid(targetObj, validationObj) {
validateParams(targetObj, validationObj);
var validationKeys = Object.keys(validationObj);
var toReturn = false;
if (targetObj instanceof Array) {
toReturn = targetObj.map(function (object) {
return isValid(object, validationObj);
});
} else {
toReturn = validationKeys.reduce(function (result, validationKey) {
if (result) {
var _ret = function () {
var validationInputObj = validationObj[validationKey];
var validationInputKeys = Object.keys(validationInputObj);
return {
v: validationInputKeys.reduce(function (result, inputKey) {
if (result) {
var valdationProp = validationInputObj[inputKey];
var resultObj = resolveNestedObject(targetObj, validationKey);
if (valdationProp.isValid instanceof Function) {
return valdationProp.isValid(resultObj);
} else {
return true;
}
} else {
return result;
}
}, true)
};
}();
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
} else {
return result;
}
}, true);
}
return toReturn;
}
// Returns a promise resolving to true if all validations are valid
// and resolving to false if a validation failed
function isValidAsync(targetObj, validationObj) {
try {
validateParams(targetObj, validationObj);
} catch (err) {
return Promise.reject(err);
}
var validationKeys = Object.keys(validationObj);
var toReturn = undefined;
if (targetObj instanceof Array) {
toReturn = Promise.all(targetObj.map(function (object) {
return isValidAsync(object, validationObj);
}));
} else {
if (validationKeys.length > 0) {
var validationPromises = validationKeys.map(function (validationKey) {
var validationInputObj = validationObj[validationKey];
var validationInputKeys = Object.keys(validationInputObj);
var validationInputPromises = validationInputKeys.map(function (inputKey) {
var valdationProp = validationInputObj[inputKey];
var resultObj = resolveNestedObject(targetObj, validationKey);
if (valdationProp.isValid instanceof Function) {
return Promise.resolve(valdationProp.isValid(resultObj));
} else {
return Promise.resolve(true);
}
});
return Promise.all(validationInputPromises).then(function (validationInputResults) {
return validationInputResults.reduce(functionalAnd);
});
}, true);
toReturn = Promise.all(validationPromises).then(function (validationResults) {
return validationResults.reduce(functionalAnd);
});
} else {
// If there are no constraints every object is valid
toReturn = Promise.resolve(true);
}
}
return toReturn;
}
// Returns an array of validation messages for each validation prop
// that fails for a single validation input
function messages(targetObj, validationObj, validationInput) {
validateParams(targetObj, validationObj);
validateInputKey(validationObj, validationInput);
var keys = Object.keys(validationObj[validationInput]);
var toReturn = undefined;
if (targetObj instanceof Array) {
toReturn = targetObj.map(function (object) {
return messages(object, validationObj, validationInput);
});
} else {
toReturn = keys.map(function (key) {
var validationProp = validationObj[validationInput][key];
var resultObj = resolveNestedObject(targetObj, validationInput);
var message = validationProp.message instanceof Function ? validationProp.message(resultObj) : validationProp.message;
if (!validationProp.isValid(resultObj)) {
return {
key: key,
message: message
};
}
}).filter(isNotUndefined).reduce(reduceToObject, {});
}
return toReturn;
}
// Returns a promise resolving to an array of validation messages
// for each validation prop that fails for a single validation input
function messagesAsync(targetObj, validationObj, validationInput) {
try {
validateParams(targetObj, validationObj);
validateInputKey(validationObj, validationInput);
} catch (err) {
return Promise.reject(err);
}
var keys = Object.keys(validationObj[validationInput]);
var toReturn = undefined;
if (targetObj instanceof Array) {
toReturn = Promise.all(targetObj.map(function (object) {
return messagesAsync(object, validationObj, validationInput);
}));
} else {
var validationPromises = keys.map(function (key) {
var validationProp = validationObj[validationInput][key];
var resultObj = resolveNestedObject(targetObj, validationInput);
var message = validationProp.message instanceof Function ? validationProp.message(resultObj) : validationProp.message;
return Promise.resolve(validationProp.isValid(resultObj)).then(function (validationPropKey, isValid) {
if (!isValid) {
return {
key: validationPropKey,
message: message
};
}
}.bind(null, key));
});
toReturn = Promise.all(validationPromises).then(function (message) {
return message.filter(isNotUndefined).reduce(reduceToObject, {});
});
}
return toReturn;
}
// Returns an array of objects, one object for each validation
// input, with each key on that object being the failed validation
// prop, and the value is the validation message
function allMessages(targetObj, validationObj) {
validateParams(targetObj, validationObj);
var keys = Object.keys(validationObj);
var toReturn = undefined;
if (targetObj instanceof Array) {
toReturn = targetObj.map(function (object) {
return allMessages(object, validationObj);
});
} else {
toReturn = keys.reduce(function (result, key) {
var validationInputObj = validationObj[key];
var validationInputKeys = Object.keys(validationInputObj);
var validationResult = {};
validationInputKeys.forEach(function (inputKey) {
var validationProp = validationInputObj[inputKey];
var resultObj = resolveNestedObject(targetObj, key);
var message = validationProp.message instanceof Function ? validationProp.message(resultObj) : validationProp.message;
if (!validationProp.isValid(resultObj)) {
validationResult[inputKey] = message;
}
});
if (Object.keys(validationResult).length > 0) {
result[key] = validationResult;
}
return result;
}, {});
}
return toReturn;
}
// Returns a promise resolving to an array of objects, one object for
// each validation input, with each key on that object being the failed
// validation prop, and the value is the validation message
function allMessagesAsync(targetObj, validationObj) {
try {
validateParams(targetObj, validationObj);
} catch (err) {
return Promise.reject(err);
}
var keys = Object.keys(validationObj);
var toReturn = undefined;
if (targetObj instanceof Array) {
toReturn = Promise.all(targetObj.map(function (object) {
return allMessagesAsync(object, validationObj);
}));
} else {
var validationPromises = keys.map(function (key) {
var validationInputObj = validationObj[key];
var validationInputKeys = Object.keys(validationInputObj);
var validationInputPromises = validationInputKeys.map(function (inputKey) {
var validationProp = validationInputObj[inputKey];
var resultObj = resolveNestedObject(targetObj, key);
var message = validationProp.message instanceof Function ? validationProp.message(resultObj) : validationProp.message;
return Promise.resolve(validationProp.isValid(resultObj)).then(function (isValid) {
if (!isValid) {
return {
message: message,
key: inputKey
};
}
});
});
return Promise.all(validationInputPromises).then(function (validationInputResults) {
var resultObj = validationInputResults.reduce(function (result, current) {
result[current.key] = current.message;
return result;
}, {});
resultObj.inputKey = key;
return resultObj;
});
});
toReturn = Promise.all(validationPromises).then(function (allMessages) {
return allMessages.reduce(function (result, current) {
result[current.inputKey] = current;
delete current.inputKey;
return result;
}, {});
});
}
return toReturn;
}
// Returns an object that contains all the attributes of
// the target object that are being validated
function cleanAttributes(targetObj, validationObj) {
validateParams(targetObj, validationObj);
var keys = Object.keys(validationObj);
var toReturn = undefined;
if (targetObj instanceof Array) {
toReturn = targetObj.map(function (object) {
return cleanAttributes(object, validationObj);
});
} else {
toReturn = {};
keys.forEach(function (key) {
var isNestedKey = key.indexOf('.') > -1;
if (!isNestedKey) {
toReturn[key] = targetObj[key];
} else {
var rootKey = key.split('.')[0];
toReturn[rootKey] = targetObj[rootKey];
}
});
}
return toReturn;
}
// Default export object with all functions as properties
exports.default = {
isValid: isValid,
isValidAsync: isValidAsync,
messages: messages,
messagesAsync: messagesAsync,
allMessages: allMessages,
allMessagesAsync: allMessagesAsync,
cleanAttributes: cleanAttributes
};
/***/ }
/******/ ]);