UNPKG

immutable-validation

Version:
200 lines (148 loc) 7.35 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _immutable = require('immutable'); var _immutable2 = _interopRequireDefault(_immutable); var _curry = require('ramda/src/curry'); var _curry2 = _interopRequireDefault(_curry); var _pipe = require('ramda/src/pipe'); var _pipe2 = _interopRequireDefault(_pipe); var _both = require('ramda/src/both'); var _both2 = _interopRequireDefault(_both); var _tap2 = require('ramda/src/tap'); var _tap3 = _interopRequireDefault(_tap2); var _util = require('./util'); var _ValidatorWrapper = require('./ValidatorWrapper'); var _ValidatorWrapper2 = _interopRequireDefault(_ValidatorWrapper); var _ValidationRecord = require('./ValidationRecord'); var _ValidationRecord2 = _interopRequireDefault(_ValidationRecord); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var MESSAGE = 'message'; var RULES = 'rules'; var IS_VALID = 'isValid'; function assertRuleResult(result) { var interfaceErr = new Error('Rules must return a result with the\n properties `isValid` and `message`.\n Use ImmutableValidation.rule()'); (0, _util.assert)((0, _both2.default)((0, _util.maybeHas)(IS_VALID), (0, _util.maybeHas)(MESSAGE))(result), interfaceErr); } function assertIterable(propName) { var iterableErr = new TypeError('`' + propName + '` is a non-iterable value.\n ruleForEach applies a validation rule to\n each item in an iterable'); return function (obj) { return (0, _util.assert)((0, _util.isIterable)(obj), iterableErr); }; } var reduceRules = (0, _curry2.default)(function (data, messagesForProp, rule) { var _tap = (0, _tap3.default)(assertRuleResult, rule(data)); var isValid = _tap.isValid; var message = _tap.message; return !isValid ? messagesForProp.add(message) : messagesForProp; }); var createResult = _ValidationRecord2.default.create; var evaluateRules = (0, _curry2.default)(function (rules, data) { return rules.reduce(reduceRules(data), _immutable2.default.Set()); }); var evaluateValidator = (0, _curry2.default)(function (validator, data) { return validator.validate(data); }); var merge = (0, _curry2.default)(function (propName, vState, result) { return result.mergeDeepWith(function (prev, next, key) { return key === IS_VALID ? prev && next : next; }, vState.getIn([RULES, propName])); }); var setResult = (0, _curry2.default)(function (propName, vState, result) { return vState.set(IS_VALID, vState.get('isValid') && result.get('isValid')).setIn([RULES, propName], result); }); function buildRuleSet(propName, getData, rules) { var evaluateData = evaluateRules(rules); var mergeWithExisting = merge(propName); var setForProp = setResult(propName); return function (vState, data) { return (0, _pipe2.default)(getData, evaluateData, createResult, mergeWithExisting(vState), setForProp(vState))(data); }; } function buildRuleSetForValidator(propName, getData, validator) { var evaluateData = evaluateValidator(validator); var mergeWithExisting = merge(propName); var setForProp = setResult(propName); return function (vState, data) { return (0, _pipe2.default)(getData, evaluateData, mergeWithExisting(vState), setForProp(vState))(data); }; } function buildRuleSetForEachValidator(propName, getData, validator) { return function (vState, data) { var iter = (0, _tap3.default)(assertIterable(propName), getData(data)); var result = iter.reduce(function (record, item, i) { return setResult(i, record, validator.validate(item)); }, createResult()); return setResult(propName, vState, result); }; } function buildRuleSetForEachItem(propName, getData, rules) { var evaluateData = evaluateRules(rules); return function (vState, data) { var iter = (0, _tap3.default)(assertIterable(propName), getData(data)); var result = iter.reduce(function (record, item, i) { return (0, _pipe2.default)(evaluateData, createResult, setResult(i, record))(item); }, createResult()); return setResult(propName, vState, result); }; } function extendRuleSets(baseValidator, ruleSet) { var extendedValidator = new Validator(); extendedValidator.ruleSets = baseValidator.ruleSets.concat(ruleSet); return extendedValidator; } var Validator = function () { function Validator() { _classCallCheck(this, Validator); this.ruleSets = []; this.validationState = _immutable2.default.Map({ isValid: true }); } _createClass(Validator, [{ key: 'ruleFor', value: function ruleFor(propName, accessor) { for (var _len = arguments.length, rules = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { rules[_key - 2] = arguments[_key]; } var ruleSet = Validator.isInstance(rules[0]) ? buildRuleSetForValidator(propName, accessor, rules[0]) : buildRuleSet(propName, accessor, rules); return extendRuleSets(this, ruleSet); } }, { key: 'ruleForEach', value: function ruleForEach(propName, accessor) { for (var _len2 = arguments.length, rules = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { rules[_key2 - 2] = arguments[_key2]; } var ruleSet = Validator.isInstance(rules[0]) ? buildRuleSetForEachValidator(propName, accessor, rules[0]) : buildRuleSetForEachItem(propName, accessor, rules); return extendRuleSets(this, ruleSet); } }, { key: 'validate', value: function validate(dataToValidate) { this.validationState = this.ruleSets.reduce(function (messages, ruleSet) { return ruleSet(messages, dataToValidate); }, _ValidationRecord2.default.create()); return this.validationState; } }], [{ key: 'isInstance', value: function isInstance(obj) { if (!obj) return false; return (0, _util.isFunction)(obj.validate); } }, { key: 'which', value: function which(chooseValidator) { if (!(0, _util.isFunction)(chooseValidator)) { throw new TypeError('Call Validator.which with a function returning a validator or null'); } return new _ValidatorWrapper2.default(chooseValidator); } }]); return Validator; }(); exports.default = Validator;