diff --git a/CHANGELOG.md b/CHANGELOG.md index a6028e6..64ebfb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - New rule `optionalAsync` for asynchronous, optional validation ([#206](https://github.com/imbrn/v8n/issues/206)) +- New modifier `strict` for schema validation ([#191](https://github.com/imbrn/v8n/issues/191), [#179](https://github.com/imbrn/v8n/issues/179)) ## [1.4.0] - 2022-02-17 diff --git a/dist/v8n.amd.js b/dist/v8n.amd.js index b0f5bc3..8b12a4d 100644 --- a/dist/v8n.amd.js +++ b/dist/v8n.amd.js @@ -11,13 +11,13 @@ define(function () { 'use strict'; var fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = function () { return false; }; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex$1) { return false; } @@ -25,14 +25,14 @@ define(function () { 'use strict'; Rule.prototype._check = function _check (value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), function (it) { return it; })(false)) { + if (testAux(this.modifiers.slice(), function (it) { return it; }, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } }; @@ -43,7 +43,8 @@ define(function () { 'use strict'; return new Promise(function (resolve, reject) { testAsyncAux( this$1.modifiers.slice(), - this$1.fn + this$1.fn, + this$1 )(value) .then(function (valid) { if (valid) { @@ -62,21 +63,21 @@ define(function () { 'use strict'; return typeof fn === 'object' ? fn[variant] : fn; } - function testAux(modifiers, fn) { + function testAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + var nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } - function testAsyncAux(modifiers, fn) { + function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + var nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return function (value) { return Promise.resolve(pickFn(fn, 'async')(value)); }; } @@ -304,8 +305,40 @@ define(function () { 'use strict'; simple: function (fn) { return function (value) { return value !== false && split(value).every(fn); }; }, async: function (fn) { return function (value) { return Promise.all(split(value).map(fn)).then(function (result) { return result.every(Boolean); }); }; }, }, + + strict: { + simple: function (fn, rule) { return function (value) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }; }, + async: function (fn, rule) { return function (value) { return Promise.resolve(fn(value)) + .then(function (result) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(function () { return false; }); }; }, + }, }; + function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); + } + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/dist/v8n.browser.js b/dist/v8n.browser.js index 43a96db..c40e750 100644 --- a/dist/v8n.browser.js +++ b/dist/v8n.browser.js @@ -12,13 +12,13 @@ var v8n = (function () { var fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = function () { return false; }; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex$1) { return false; } @@ -26,14 +26,14 @@ var v8n = (function () { Rule.prototype._check = function _check (value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), function (it) { return it; })(false)) { + if (testAux(this.modifiers.slice(), function (it) { return it; }, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } }; @@ -44,7 +44,8 @@ var v8n = (function () { return new Promise(function (resolve, reject) { testAsyncAux( this$1.modifiers.slice(), - this$1.fn + this$1.fn, + this$1 )(value) .then(function (valid) { if (valid) { @@ -63,21 +64,21 @@ var v8n = (function () { return typeof fn === 'object' ? fn[variant] : fn; } - function testAux(modifiers, fn) { + function testAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + var nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } - function testAsyncAux(modifiers, fn) { + function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + var nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return function (value) { return Promise.resolve(pickFn(fn, 'async')(value)); }; } @@ -305,8 +306,40 @@ var v8n = (function () { simple: function (fn) { return function (value) { return value !== false && split(value).every(fn); }; }, async: function (fn) { return function (value) { return Promise.all(split(value).map(fn)).then(function (result) { return result.every(Boolean); }); }; }, }, + + strict: { + simple: function (fn, rule) { return function (value) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }; }, + async: function (fn, rule) { return function (value) { return Promise.resolve(fn(value)) + .then(function (result) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(function () { return false; }); }; }, + }, }; + function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); + } + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/dist/v8n.browser.min.js b/dist/v8n.browser.min.js index 43c29d0..1d686ae 100644 --- a/dist/v8n.browser.min.js +++ b/dist/v8n.browser.min.js @@ -1,2 +1,2 @@ -var v8n=function(){"use strict";var n=function(n,t,r,e){this.name=n,this.fn=t,this.args=r,this.modifiers=e};function t(n,t){return void 0===t&&(t="simple"),"object"==typeof n?n[t]:n}function r(n,e){if(n.length){var u=n.shift(),i=r(n,e);return u.perform(i)}return t(e)}function e(n,r){if(n.length){var u=n.shift(),i=e(n,r);return u.performAsync(i)}return function(n){return Promise.resolve(t(r,"async")(n))}}n.prototype._test=function(n){var t=this.fn;try{r(this.modifiers.slice(),t)(n)}catch(n){t=function(){return!1}}try{return r(this.modifiers.slice(),t)(n)}catch(n){return!1}},n.prototype._check=function(n){try{r(this.modifiers.slice(),this.fn)(n)}catch(n){if(r(this.modifiers.slice(),(function(n){return n}))(!1))return}if(!r(this.modifiers.slice(),this.fn)(n))throw null},n.prototype._testAsync=function(n){var t=this;return new Promise((function(r,u){e(t.modifiers.slice(),t.fn)(n).then((function(t){t?r(n):u(null)})).catch((function(n){return u(n)}))}))};var u=function(n,t,r){this.name=n,this.perform=t,this.performAsync=r},i=function(n){function t(r,e,u,i){for(var o=[],c=arguments.length-4;c-- >0;)o[c]=arguments[c+4];n.call(this,o),n.captureStackTrace&&n.captureStackTrace(this,t),this.rule=r,this.value=e,this.cause=u,this.target=i}return n&&(t.__proto__=n),t.prototype=Object.create(n&&n.prototype),t.prototype.constructor=t,t}(Error),o=function(n,t){void 0===n&&(n=[]),void 0===t&&(t=[]),this.chain=n,this.nextRuleModifiers=t};function c(n,t,r,e){if(t.length){var u=t.shift();u._testAsync(n).then((function(){c(n,t,r,e)}),(function(t){e(new i(u,n,t))}))}else r(n)}function f(){return void 0!==typeof Proxy?a(new o):h(new o)}o.prototype._applyRule=function(t,r){var e=this;return function(){for(var u=[],i=arguments.length;i--;)u[i]=arguments[i];return e.chain.push(new n(r,t.apply(e,u),u,e.nextRuleModifiers)),e.nextRuleModifiers=[],e}},o.prototype._applyModifier=function(n,t){return this.nextRuleModifiers.push(new u(t,n.simple,n.async)),this},o.prototype._clone=function(){return new o(this.chain.slice(),this.nextRuleModifiers.slice())},o.prototype.test=function(n){return this.chain.every((function(t){return t._test(n)}))},o.prototype.testAll=function(n){var t=[];return this.chain.forEach((function(r){try{r._check(n)}catch(e){t.push(new i(r,n,e))}})),t},o.prototype.check=function(n){this.chain.forEach((function(t){try{t._check(n)}catch(r){throw new i(t,n,r)}}))},o.prototype.testAsync=function(n){var t=this;return new Promise((function(r,e){c(n,t.chain.slice(),r,e)}))};var s={};function a(n){return new Proxy(n,{get:function(t,r){if(r in t)return t[r];var e=a(n._clone());return r in l?e._applyModifier(l[r],r):r in s?e._applyRule(s[r],r):r in y?e._applyRule(y[r],r):void 0}})}function h(n){var t=function(n,t){return Object.keys(n).forEach((function(r){t[r]=function(){for(var e=[],u=arguments.length;u--;)e[u]=arguments[u];var i=h(t._clone()),o=i._applyRule(n[r],r).apply(void 0,e);return o}})),t},r=t(y,n),e=t(s,r);return Object.keys(l).forEach((function(n){Object.defineProperty(e,n,{get:function(){return h(e._clone())._applyModifier(l[n],n)}})})),e}f.extend=function(n){Object.assign(s,n)},f.clearCustomRules=function(){s={}};var l={not:{simple:function(n){return function(t){return!n(t)}},async:function(n){return function(t){return Promise.resolve(n(t)).then((function(n){return!n})).catch((function(){return!0}))}}},some:{simple:function(n){return function(t){return p(t).some((function(t){try{return n(t)}catch(n){return!1}}))}},async:function(n){return function(t){return Promise.all(p(t).map((function(t){try{return n(t).catch((function(){return!1}))}catch(n){return!1}}))).then((function(n){return n.some(Boolean)}))}}},every:{simple:function(n){return function(t){return!1!==t&&p(t).every(n)}},async:function(n){return function(t){return Promise.all(p(t).map(n)).then((function(n){return n.every(Boolean)}))}}}};function p(n){return"string"==typeof n?n.split(""):n}var y={equal:function(n){return function(t){return t==n}},exact:function(n){return function(t){return t===n}},number:function(n){return void 0===n&&(n=!0),function(t){return"number"==typeof t&&(n||isFinite(t))}},integer:function(){return function(n){return(Number.isInteger||g)(n)}},numeric:function(){return function(n){return!isNaN(parseFloat(n))&&isFinite(n)}},string:function(){return v("string")},boolean:function(){return v("boolean")},undefined:function(){return v("undefined")},null:function(){return v("null")},array:function(){return v("array")},object:function(){return v("object")},instanceOf:function(n){return function(t){return t instanceof n}},pattern:function(n){return function(t){return n.test(t)}},lowercase:function(){return function(n){return/^([a-z]+\s*)+$/.test(n)}},uppercase:function(){return function(n){return/^([A-Z]+\s*)+$/.test(n)}},vowel:function(){return function(n){return/^[aeiou]+$/i.test(n)}},consonant:function(){return function(n){return/^(?=[^aeiou])([a-z]+)$/i.test(n)}},first:function(n){return function(t){return t[0]==n}},last:function(n){return function(t){return t[t.length-1]==n}},empty:function(){return function(n){return 0===n.length}},length:function(n,t){return function(r){return r.length>=n&&r.length<=(t||n)}},minLength:function(n){return function(t){return t.length>=n}},maxLength:function(n){return function(t){return t.length<=n}},negative:function(){return function(n){return n<0}},positive:function(){return function(n){return n>=0}},between:function(n,t){return function(r){return r>=n&&r<=t}},range:function(n,t){return function(r){return r>=n&&r<=t}},lessThan:function(n){return function(t){return tn}},greaterThanOrEqual:function(n){return function(t){return t>=n}},even:function(){return function(n){return n%2==0}},odd:function(){return function(n){return n%2!=0}},includes:function(n){return function(t){return~t.indexOf(n)}},schema:function(n){return function(n){return{simple:function(t){var r=[];if(Object.keys(n).forEach((function(e){var u=n[e];try{u.check((t||{})[e])}catch(n){n.target=e,r.push(n)}})),r.length>0)throw r;return!0},async:function(t){var r=[],e=Object.keys(n).map((function(e){return n[e].testAsync((t||{})[e]).catch((function(n){n.target=e,r.push(n)}))}));return Promise.all(e).then((function(){if(r.length>0)throw r;return!0}))}}}(n)},passesAnyOf:function(){for(var n=[],t=arguments.length;t--;)n[t]=arguments[t];return function(t){return n.some((function(n){return n.test(t)}))}},optional:m(!1),optionalAsync:m(!0)};function m(n){return function(t,r){return void 0===r&&(r=!1),function(e){if(r&&"string"==typeof e&&""===e.trim())return!0;if(null!=e){if(n)return t.testAsync(e);t.check(e)}return!0}}}function v(n){return function(t){return Array.isArray(t)&&"array"===n||null===t&&"null"===n||typeof t===n}}function g(n){return"number"==typeof n&&isFinite(n)&&Math.floor(n)===n}return f}(); +var v8n=function(){"use strict";var n=function(n,t,r,e){this.name=n,this.fn=t,this.args=r,this.modifiers=e};function t(n,t){return void 0===t&&(t="simple"),"object"==typeof n?n[t]:n}function r(n,e,u){if(n.length){var i=n.shift(),o=r(n,e,u);return i.perform(o,u)}return t(e)}function e(n,r,u){if(n.length){var i=n.shift(),o=e(n,r,u);return i.performAsync(o,u)}return function(n){return Promise.resolve(t(r,"async")(n))}}n.prototype._test=function(n){var t=this.fn;try{r(this.modifiers.slice(),t,this)(n)}catch(n){t=function(){return!1}}try{return r(this.modifiers.slice(),t,this)(n)}catch(n){return!1}},n.prototype._check=function(n){try{r(this.modifiers.slice(),this.fn,this)(n)}catch(n){if(r(this.modifiers.slice(),(function(n){return n}),this)(!1))return}if(!r(this.modifiers.slice(),this.fn,this)(n))throw null},n.prototype._testAsync=function(n){var t=this;return new Promise((function(r,u){e(t.modifiers.slice(),t.fn,t)(n).then((function(t){t?r(n):u(null)})).catch((function(n){return u(n)}))}))};var u=function(n,t,r){this.name=n,this.perform=t,this.performAsync=r},i=function(n){function t(r,e,u,i){for(var o=[],c=arguments.length-4;c-- >0;)o[c]=arguments[c+4];n.call(this,o),n.captureStackTrace&&n.captureStackTrace(this,t),this.rule=r,this.value=e,this.cause=u,this.target=i}return n&&(t.__proto__=n),t.prototype=Object.create(n&&n.prototype),t.prototype.constructor=t,t}(Error),o=function(n,t){void 0===n&&(n=[]),void 0===t&&(t=[]),this.chain=n,this.nextRuleModifiers=t};function c(n,t,r,e){if(t.length){var u=t.shift();u._testAsync(n).then((function(){c(n,t,r,e)}),(function(t){e(new i(u,n,t))}))}else r(n)}function f(){return void 0!==typeof Proxy?a(new o):h(new o)}o.prototype._applyRule=function(t,r){var e=this;return function(){for(var u=[],i=arguments.length;i--;)u[i]=arguments[i];return e.chain.push(new n(r,t.apply(e,u),u,e.nextRuleModifiers)),e.nextRuleModifiers=[],e}},o.prototype._applyModifier=function(n,t){return this.nextRuleModifiers.push(new u(t,n.simple,n.async)),this},o.prototype._clone=function(){return new o(this.chain.slice(),this.nextRuleModifiers.slice())},o.prototype.test=function(n){return this.chain.every((function(t){return t._test(n)}))},o.prototype.testAll=function(n){var t=[];return this.chain.forEach((function(r){try{r._check(n)}catch(e){t.push(new i(r,n,e))}})),t},o.prototype.check=function(n){this.chain.forEach((function(t){try{t._check(n)}catch(r){throw new i(t,n,r)}}))},o.prototype.testAsync=function(n){var t=this;return new Promise((function(r,e){c(n,t.chain.slice(),r,e)}))};var s={};function a(n){return new Proxy(n,{get:function(t,r){if(r in t)return t[r];var e=a(n._clone());return r in l?e._applyModifier(l[r],r):r in s?e._applyRule(s[r],r):r in m?e._applyRule(m[r],r):void 0}})}function h(n){var t=function(n,t){return Object.keys(n).forEach((function(r){t[r]=function(){for(var e=[],u=arguments.length;u--;)e[u]=arguments[u];var i=h(t._clone()),o=i._applyRule(n[r],r).apply(void 0,e);return o}})),t},r=t(m,n),e=t(s,r);return Object.keys(l).forEach((function(n){Object.defineProperty(e,n,{get:function(){return h(e._clone())._applyModifier(l[n],n)}})})),e}f.extend=function(n){Object.assign(s,n)},f.clearCustomRules=function(){s={}};var l={not:{simple:function(n){return function(t){return!n(t)}},async:function(n){return function(t){return Promise.resolve(n(t)).then((function(n){return!n})).catch((function(){return!0}))}}},some:{simple:function(n){return function(t){return y(t).some((function(t){try{return n(t)}catch(n){return!1}}))}},async:function(n){return function(t){return Promise.all(y(t).map((function(t){try{return n(t).catch((function(){return!1}))}catch(n){return!1}}))).then((function(n){return n.some(Boolean)}))}}},every:{simple:function(n){return function(t){return!1!==t&&y(t).every(n)}},async:function(n){return function(t){return Promise.all(y(t).map(n)).then((function(n){return n.every(Boolean)}))}}},strict:{simple:function(n,t){return function(r){return p(t)&&r&&"object"==typeof r?Object.keys(t.args[0]).length===Object.keys(r).length&&n(r):n(r)}},async:function(n,t){return function(r){return Promise.resolve(n(r)).then((function(n){return p(t)&&r&&"object"==typeof r?Object.keys(t.args[0]).length===Object.keys(r).length&&n:n})).catch((function(){return!1}))}}}};function p(n){return n&&"schema"===n.name&&n.args.length>0&&"object"==typeof n.args[0]}function y(n){return"string"==typeof n?n.split(""):n}var m={equal:function(n){return function(t){return t==n}},exact:function(n){return function(t){return t===n}},number:function(n){return void 0===n&&(n=!0),function(t){return"number"==typeof t&&(n||isFinite(t))}},integer:function(){return function(n){return(Number.isInteger||d)(n)}},numeric:function(){return function(n){return!isNaN(parseFloat(n))&&isFinite(n)}},string:function(){return g("string")},boolean:function(){return g("boolean")},undefined:function(){return g("undefined")},null:function(){return g("null")},array:function(){return g("array")},object:function(){return g("object")},instanceOf:function(n){return function(t){return t instanceof n}},pattern:function(n){return function(t){return n.test(t)}},lowercase:function(){return function(n){return/^([a-z]+\s*)+$/.test(n)}},uppercase:function(){return function(n){return/^([A-Z]+\s*)+$/.test(n)}},vowel:function(){return function(n){return/^[aeiou]+$/i.test(n)}},consonant:function(){return function(n){return/^(?=[^aeiou])([a-z]+)$/i.test(n)}},first:function(n){return function(t){return t[0]==n}},last:function(n){return function(t){return t[t.length-1]==n}},empty:function(){return function(n){return 0===n.length}},length:function(n,t){return function(r){return r.length>=n&&r.length<=(t||n)}},minLength:function(n){return function(t){return t.length>=n}},maxLength:function(n){return function(t){return t.length<=n}},negative:function(){return function(n){return n<0}},positive:function(){return function(n){return n>=0}},between:function(n,t){return function(r){return r>=n&&r<=t}},range:function(n,t){return function(r){return r>=n&&r<=t}},lessThan:function(n){return function(t){return tn}},greaterThanOrEqual:function(n){return function(t){return t>=n}},even:function(){return function(n){return n%2==0}},odd:function(){return function(n){return n%2!=0}},includes:function(n){return function(t){return~t.indexOf(n)}},schema:function(n){return function(n){return{simple:function(t){var r=[];if(Object.keys(n).forEach((function(e){var u=n[e];try{u.check((t||{})[e])}catch(n){n.target=e,r.push(n)}})),r.length>0)throw r;return!0},async:function(t){var r=[],e=Object.keys(n).map((function(e){return n[e].testAsync((t||{})[e]).catch((function(n){n.target=e,r.push(n)}))}));return Promise.all(e).then((function(){if(r.length>0)throw r;return!0}))}}}(n)},passesAnyOf:function(){for(var n=[],t=arguments.length;t--;)n[t]=arguments[t];return function(t){return n.some((function(n){return n.test(t)}))}},optional:v(!1),optionalAsync:v(!0)};function v(n){return function(t,r){return void 0===r&&(r=!1),function(e){if(r&&"string"==typeof e&&""===e.trim())return!0;if(null!=e){if(n)return t.testAsync(e);t.check(e)}return!0}}}function g(n){return function(t){return Array.isArray(t)&&"array"===n||null===t&&"null"===n||typeof t===n}}function d(n){return"number"==typeof n&&isFinite(n)&&Math.floor(n)===n}return f}(); //# sourceMappingURL=v8n.browser.min.js.map diff --git a/dist/v8n.browser.min.js.map b/dist/v8n.browser.min.js.map index 9840d0e..50dedea 100644 --- a/dist/v8n.browser.min.js.map +++ b/dist/v8n.browser.min.js.map @@ -1 +1 @@ -{"version":3,"file":"v8n.browser.min.js","sources":["../src/Rule.js","../src/Modifier.js","../src/ValidationError.js","../src/Context.js","../src/v8n.js"],"sourcesContent":["class Rule {\r\n constructor(name, fn, args, modifiers) {\r\n this.name = name;\r\n this.fn = fn;\r\n this.args = args;\r\n this.modifiers = modifiers;\r\n }\r\n\r\n _test(value) {\r\n let fn = this.fn;\r\n\r\n try {\r\n testAux(this.modifiers.slice(), fn)(value);\r\n } catch (ex) {\r\n fn = () => false;\r\n }\r\n\r\n try {\r\n return testAux(this.modifiers.slice(), fn)(value);\r\n } catch (ex) {\r\n return false;\r\n }\r\n }\r\n\r\n _check(value) {\r\n try {\r\n testAux(this.modifiers.slice(), this.fn)(value);\r\n } catch (ex) {\r\n if (testAux(this.modifiers.slice(), it => it)(false)) {\r\n return;\r\n }\r\n }\r\n\r\n if (!testAux(this.modifiers.slice(), this.fn)(value)) {\r\n throw null;\r\n }\r\n }\r\n\r\n _testAsync(value) {\r\n return new Promise((resolve, reject) => {\r\n testAsyncAux(\r\n this.modifiers.slice(),\r\n this.fn,\r\n )(value)\r\n .then(valid => {\r\n if (valid) {\r\n resolve(value);\r\n } else {\r\n reject(null);\r\n }\r\n })\r\n .catch(ex => reject(ex));\r\n });\r\n }\r\n}\r\n\r\nfunction pickFn(fn, variant = 'simple') {\r\n return typeof fn === 'object' ? fn[variant] : fn;\r\n}\r\n\r\nfunction testAux(modifiers, fn) {\r\n if (modifiers.length) {\r\n const modifier = modifiers.shift();\r\n const nextFn = testAux(modifiers, fn);\r\n return modifier.perform(nextFn);\r\n } else {\r\n return pickFn(fn);\r\n }\r\n}\r\n\r\nfunction testAsyncAux(modifiers, fn) {\r\n if (modifiers.length) {\r\n const modifier = modifiers.shift();\r\n const nextFn = testAsyncAux(modifiers, fn);\r\n return modifier.performAsync(nextFn);\r\n } else {\r\n return value => Promise.resolve(pickFn(fn, 'async')(value));\r\n }\r\n}\r\n\r\nexport default Rule;\r\n","class Modifier {\r\n constructor(name, perform, performAsync) {\r\n this.name = name;\r\n this.perform = perform;\r\n this.performAsync = performAsync;\r\n }\r\n}\r\n\r\nexport default Modifier;\r\n","class ValidationError extends Error {\r\n constructor(rule, value, cause, target, ...remaining) {\r\n super(remaining);\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, ValidationError);\r\n }\r\n this.rule = rule;\r\n this.value = value;\r\n this.cause = cause;\r\n this.target = target;\r\n }\r\n}\r\n\r\nexport default ValidationError;\r\n","import Rule from './Rule';\r\nimport Modifier from './Modifier';\r\nimport ValidationError from './ValidationError';\r\n\r\nclass Context {\r\n constructor(chain = [], nextRuleModifiers = []) {\r\n this.chain = chain;\r\n this.nextRuleModifiers = nextRuleModifiers;\r\n }\r\n\r\n _applyRule(ruleFn, name) {\r\n return (...args) => {\r\n this.chain.push(\r\n new Rule(name, ruleFn.apply(this, args), args, this.nextRuleModifiers),\r\n );\r\n this.nextRuleModifiers = [];\r\n return this;\r\n };\r\n }\r\n\r\n _applyModifier(modifier, name) {\r\n this.nextRuleModifiers.push(\r\n new Modifier(name, modifier.simple, modifier.async),\r\n );\r\n return this;\r\n }\r\n\r\n _clone() {\r\n return new Context(this.chain.slice(), this.nextRuleModifiers.slice());\r\n }\r\n\r\n test(value) {\r\n return this.chain.every(rule => rule._test(value));\r\n }\r\n\r\n testAll(value) {\r\n const err = [];\r\n this.chain.forEach(rule => {\r\n try {\r\n rule._check(value);\r\n } catch (ex) {\r\n err.push(new ValidationError(rule, value, ex));\r\n }\r\n });\r\n return err;\r\n }\r\n\r\n check(value) {\r\n this.chain.forEach(rule => {\r\n try {\r\n rule._check(value);\r\n } catch (ex) {\r\n throw new ValidationError(rule, value, ex);\r\n }\r\n });\r\n }\r\n\r\n testAsync(value) {\r\n return new Promise((resolve, reject) => {\r\n executeAsyncRules(value, this.chain.slice(), resolve, reject);\r\n });\r\n }\r\n}\r\n\r\nfunction executeAsyncRules(value, rules, resolve, reject) {\r\n if (rules.length) {\r\n const rule = rules.shift();\r\n rule._testAsync(value).then(\r\n () => {\r\n executeAsyncRules(value, rules, resolve, reject);\r\n },\r\n cause => {\r\n reject(new ValidationError(rule, value, cause));\r\n },\r\n );\r\n } else {\r\n resolve(value);\r\n }\r\n}\r\n\r\nexport default Context;\r\n","import Context from './Context';\r\n\r\nfunction v8n() {\r\n return typeof Proxy !== undefined\r\n ? proxyContext(new Context())\r\n : proxylessContext(new Context());\r\n}\r\n\r\n// Custom rules\r\nlet customRules = {};\r\n\r\nv8n.extend = function(newRules) {\r\n Object.assign(customRules, newRules);\r\n};\r\n\r\nv8n.clearCustomRules = function() {\r\n customRules = {};\r\n};\r\n\r\nfunction proxyContext(context) {\r\n return new Proxy(context, {\r\n get(obj, prop) {\r\n if (prop in obj) {\r\n return obj[prop];\r\n }\r\n\r\n const newContext = proxyContext(context._clone());\r\n\r\n if (prop in availableModifiers) {\r\n return newContext._applyModifier(availableModifiers[prop], prop);\r\n }\r\n if (prop in customRules) {\r\n return newContext._applyRule(customRules[prop], prop);\r\n }\r\n if (prop in availableRules) {\r\n return newContext._applyRule(availableRules[prop], prop);\r\n }\r\n },\r\n });\r\n}\r\n\r\nfunction proxylessContext(context) {\r\n const addRuleSet = (ruleSet, targetContext) => {\r\n Object.keys(ruleSet).forEach(prop => {\r\n targetContext[prop] = (...args) => {\r\n const newContext = proxylessContext(targetContext._clone());\r\n const contextWithRuleApplied = newContext._applyRule(\r\n ruleSet[prop],\r\n prop,\r\n )(...args);\r\n return contextWithRuleApplied;\r\n };\r\n });\r\n return targetContext;\r\n };\r\n\r\n const contextWithAvailableRules = addRuleSet(availableRules, context);\r\n const contextWithAllRules = addRuleSet(\r\n customRules,\r\n contextWithAvailableRules,\r\n );\r\n\r\n Object.keys(availableModifiers).forEach(prop => {\r\n Object.defineProperty(contextWithAllRules, prop, {\r\n get: () => {\r\n const newContext = proxylessContext(contextWithAllRules._clone());\r\n return newContext._applyModifier(availableModifiers[prop], prop);\r\n },\r\n });\r\n });\r\n\r\n return contextWithAllRules;\r\n}\r\n\r\nconst availableModifiers = {\r\n not: {\r\n simple: fn => value => !fn(value),\r\n async: fn => value =>\r\n Promise.resolve(fn(value))\r\n .then(result => !result)\r\n .catch(() => true),\r\n },\r\n\r\n some: {\r\n simple: fn => value => {\r\n return split(value).some(item => {\r\n try {\r\n return fn(item);\r\n } catch (ex) {\r\n return false;\r\n }\r\n });\r\n },\r\n async: fn => value => {\r\n return Promise.all(\r\n split(value).map(item => {\r\n try {\r\n return fn(item).catch(() => false);\r\n } catch (ex) {\r\n return false;\r\n }\r\n }),\r\n ).then(result => result.some(Boolean));\r\n },\r\n },\r\n\r\n every: {\r\n simple: fn => value => value !== false && split(value).every(fn),\r\n async: fn => value =>\r\n Promise.all(split(value).map(fn)).then(result => result.every(Boolean)),\r\n },\r\n};\r\n\r\nfunction split(value) {\r\n if (typeof value === 'string') {\r\n return value.split('');\r\n }\r\n return value;\r\n}\r\n\r\nconst availableRules = {\r\n // Value\r\n\r\n equal: expected => value => value == expected,\r\n\r\n exact: expected => value => value === expected,\r\n\r\n // Types\r\n\r\n number: (allowInfinite = true) => value =>\r\n typeof value === 'number' && (allowInfinite || isFinite(value)),\r\n\r\n integer: () => value => {\r\n const isInteger = Number.isInteger || isIntegerPolyfill;\r\n return isInteger(value);\r\n },\r\n\r\n numeric: () => value => !isNaN(parseFloat(value)) && isFinite(value),\r\n\r\n string: () => testType('string'),\r\n\r\n boolean: () => testType('boolean'),\r\n\r\n undefined: () => testType('undefined'),\r\n\r\n null: () => testType('null'),\r\n\r\n array: () => testType('array'),\r\n\r\n object: () => testType('object'),\r\n\r\n instanceOf: instance => value => value instanceof instance,\r\n\r\n // Pattern\r\n\r\n pattern: expected => value => expected.test(value),\r\n\r\n lowercase: () => value => /^([a-z]+\\s*)+$/.test(value),\r\n\r\n uppercase: () => value => /^([A-Z]+\\s*)+$/.test(value),\r\n\r\n vowel: () => value => /^[aeiou]+$/i.test(value),\r\n\r\n consonant: () => value => /^(?=[^aeiou])([a-z]+)$/i.test(value),\r\n\r\n // Value at\r\n\r\n first: expected => value => value[0] == expected,\r\n\r\n last: expected => value => value[value.length - 1] == expected,\r\n\r\n // Length\r\n\r\n empty: () => value => value.length === 0,\r\n\r\n length: (min, max) => value =>\r\n value.length >= min && value.length <= (max || min),\r\n\r\n minLength: min => value => value.length >= min,\r\n\r\n maxLength: max => value => value.length <= max,\r\n\r\n // Range\r\n\r\n negative: () => value => value < 0,\r\n\r\n positive: () => value => value >= 0,\r\n\r\n between: (a, b) => value => value >= a && value <= b,\r\n\r\n range: (a, b) => value => value >= a && value <= b,\r\n\r\n lessThan: n => value => value < n,\r\n\r\n lessThanOrEqual: n => value => value <= n,\r\n\r\n greaterThan: n => value => value > n,\r\n\r\n greaterThanOrEqual: n => value => value >= n,\r\n\r\n // Divisible\r\n\r\n even: () => value => value % 2 === 0,\r\n\r\n odd: () => value => value % 2 !== 0,\r\n\r\n includes: expected => value => ~value.indexOf(expected),\r\n\r\n schema: schema => testSchema(schema),\r\n\r\n // branching\r\n\r\n passesAnyOf: (...validations) => value =>\r\n validations.some(validation => validation.test(value)),\r\n\r\n optional: createOptionalRule(false),\r\n optionalAsync: createOptionalRule(true),\r\n};\r\n\r\nfunction createOptionalRule(asynchronous) {\r\n return (validation, considerTrimmedEmptyString = false) => value => {\r\n if (\r\n considerTrimmedEmptyString &&\r\n typeof value === 'string' &&\r\n value.trim() === ''\r\n ) {\r\n return true;\r\n }\r\n\r\n if (value !== undefined && value !== null) {\r\n if (!asynchronous) {\r\n validation.check(value);\r\n } else {\r\n return validation.testAsync(value);\r\n }\r\n }\r\n return true;\r\n };\r\n}\r\n\r\nfunction testType(expected) {\r\n return value => {\r\n return (\r\n (Array.isArray(value) && expected === 'array') ||\r\n (value === null && expected === 'null') ||\r\n typeof value === expected\r\n );\r\n };\r\n}\r\n\r\nfunction isIntegerPolyfill(value) {\r\n return (\r\n typeof value === 'number' && isFinite(value) && Math.floor(value) === value\r\n );\r\n}\r\n\r\nfunction testSchema(schema) {\r\n return {\r\n simple: value => {\r\n const causes = [];\r\n Object.keys(schema).forEach(key => {\r\n const nestedValidation = schema[key];\r\n try {\r\n nestedValidation.check((value || {})[key]);\r\n } catch (ex) {\r\n ex.target = key;\r\n causes.push(ex);\r\n }\r\n });\r\n if (causes.length > 0) {\r\n throw causes;\r\n }\r\n return true;\r\n },\r\n async: value => {\r\n const causes = [];\r\n const nested = Object.keys(schema).map(key => {\r\n const nestedValidation = schema[key];\r\n return nestedValidation.testAsync((value || {})[key]).catch(ex => {\r\n ex.target = key;\r\n causes.push(ex);\r\n });\r\n });\r\n return Promise.all(nested).then(() => {\r\n if (causes.length > 0) {\r\n throw causes;\r\n }\r\n\r\n return true;\r\n });\r\n },\r\n };\r\n}\r\n\r\nexport default v8n;\r\n"],"names":["Rule","name","fn","args","modifiers","this","pickFn","variant","testAux","length","const","modifier","shift","nextFn","perform","testAsyncAux","performAsync","value","Promise","resolve","_test","let","slice","ex","_check","it","_testAsync","reject","then","valid","catch","Modifier","ValidationError","rule","cause","target","super","remaining","Error","captureStackTrace","Context","chain","nextRuleModifiers","executeAsyncRules","rules","v8n","undefined","Proxy","proxyContext","proxylessContext","_applyRule","ruleFn","push","apply","_applyModifier","simple","async","_clone","test","every","testAll","err","forEach","check","testAsync","customRules","context","get","obj","prop","newContext","availableModifiers","availableRules","addRuleSet","ruleSet","targetContext","Object","keys","contextWithRuleApplied","contextWithAvailableRules","contextWithAllRules","defineProperty","extend","newRules","assign","clearCustomRules","not","result","some","split","item","all","map","Boolean","equal","expected","exact","number","allowInfinite","isFinite","integer","Number","isInteger","isIntegerPolyfill","numeric","isNaN","parseFloat","string","testType","boolean","null","array","object","instanceOf","instance","pattern","lowercase","uppercase","vowel","consonant","first","last","empty","min","max","minLength","maxLength","negative","positive","between","a","b","range","lessThan","n","lessThanOrEqual","greaterThan","greaterThanOrEqual","even","odd","includes","indexOf","schema","causes","key","nestedValidation","nested","testSchema","passesAnyOf","validations","validation","optional","createOptionalRule","optionalAsync","asynchronous","considerTrimmedEmptyString","trim","Array","isArray","Math","floor"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"v8n.browser.min.js","sources":["../src/Rule.js","../src/Modifier.js","../src/ValidationError.js","../src/Context.js","../src/v8n.js"],"sourcesContent":["class Rule {\n constructor(name, fn, args, modifiers) {\n this.name = name;\n this.fn = fn;\n this.args = args;\n this.modifiers = modifiers;\n }\n\n _test(value) {\n let fn = this.fn;\n\n try {\n testAux(this.modifiers.slice(), fn, this)(value);\n } catch (ex) {\n fn = () => false;\n }\n\n try {\n return testAux(this.modifiers.slice(), fn, this)(value);\n } catch (ex) {\n return false;\n }\n }\n\n _check(value) {\n try {\n testAux(this.modifiers.slice(), this.fn, this)(value);\n } catch (ex) {\n if (testAux(this.modifiers.slice(), it => it, this)(false)) {\n return;\n }\n }\n\n if (!testAux(this.modifiers.slice(), this.fn, this)(value)) {\n throw null;\n }\n }\n\n _testAsync(value) {\n return new Promise((resolve, reject) => {\n testAsyncAux(\n this.modifiers.slice(),\n this.fn,\n this,\n )(value)\n .then(valid => {\n if (valid) {\n resolve(value);\n } else {\n reject(null);\n }\n })\n .catch(ex => reject(ex));\n });\n }\n}\n\nfunction pickFn(fn, variant = 'simple') {\n return typeof fn === 'object' ? fn[variant] : fn;\n}\n\nfunction testAux(modifiers, fn, rule) {\n if (modifiers.length) {\n const modifier = modifiers.shift();\n const nextFn = testAux(modifiers, fn, rule);\n return modifier.perform(nextFn, rule);\n } else {\n return pickFn(fn);\n }\n}\n\nfunction testAsyncAux(modifiers, fn, rule) {\n if (modifiers.length) {\n const modifier = modifiers.shift();\n const nextFn = testAsyncAux(modifiers, fn, rule);\n return modifier.performAsync(nextFn, rule);\n } else {\n return value => Promise.resolve(pickFn(fn, 'async')(value));\n }\n}\n\nexport default Rule;\n","class Modifier {\n constructor(name, perform, performAsync) {\n this.name = name;\n this.perform = perform;\n this.performAsync = performAsync;\n }\n}\n\nexport default Modifier;\n","class ValidationError extends Error {\n constructor(rule, value, cause, target, ...remaining) {\n super(remaining);\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n this.rule = rule;\n this.value = value;\n this.cause = cause;\n this.target = target;\n }\n}\n\nexport default ValidationError;\n","import Rule from './Rule';\nimport Modifier from './Modifier';\nimport ValidationError from './ValidationError';\n\nclass Context {\n constructor(chain = [], nextRuleModifiers = []) {\n this.chain = chain;\n this.nextRuleModifiers = nextRuleModifiers;\n }\n\n _applyRule(ruleFn, name) {\n return (...args) => {\n this.chain.push(\n new Rule(name, ruleFn.apply(this, args), args, this.nextRuleModifiers),\n );\n this.nextRuleModifiers = [];\n return this;\n };\n }\n\n _applyModifier(modifier, name) {\n this.nextRuleModifiers.push(\n new Modifier(name, modifier.simple, modifier.async),\n );\n return this;\n }\n\n _clone() {\n return new Context(this.chain.slice(), this.nextRuleModifiers.slice());\n }\n\n test(value) {\n return this.chain.every(rule => rule._test(value));\n }\n\n testAll(value) {\n const err = [];\n this.chain.forEach(rule => {\n try {\n rule._check(value);\n } catch (ex) {\n err.push(new ValidationError(rule, value, ex));\n }\n });\n return err;\n }\n\n check(value) {\n this.chain.forEach(rule => {\n try {\n rule._check(value);\n } catch (ex) {\n throw new ValidationError(rule, value, ex);\n }\n });\n }\n\n testAsync(value) {\n return new Promise((resolve, reject) => {\n executeAsyncRules(value, this.chain.slice(), resolve, reject);\n });\n }\n}\n\nfunction executeAsyncRules(value, rules, resolve, reject) {\n if (rules.length) {\n const rule = rules.shift();\n rule._testAsync(value).then(\n () => {\n executeAsyncRules(value, rules, resolve, reject);\n },\n cause => {\n reject(new ValidationError(rule, value, cause));\n },\n );\n } else {\n resolve(value);\n }\n}\n\nexport default Context;\n","import Context from './Context';\n\nfunction v8n() {\n return typeof Proxy !== undefined\n ? proxyContext(new Context())\n : proxylessContext(new Context());\n}\n\n// Custom rules\nlet customRules = {};\n\nv8n.extend = function(newRules) {\n Object.assign(customRules, newRules);\n};\n\nv8n.clearCustomRules = function() {\n customRules = {};\n};\n\nfunction proxyContext(context) {\n return new Proxy(context, {\n get(obj, prop) {\n if (prop in obj) {\n return obj[prop];\n }\n\n const newContext = proxyContext(context._clone());\n\n if (prop in availableModifiers) {\n return newContext._applyModifier(availableModifiers[prop], prop);\n }\n if (prop in customRules) {\n return newContext._applyRule(customRules[prop], prop);\n }\n if (prop in availableRules) {\n return newContext._applyRule(availableRules[prop], prop);\n }\n },\n });\n}\n\nfunction proxylessContext(context) {\n const addRuleSet = (ruleSet, targetContext) => {\n Object.keys(ruleSet).forEach(prop => {\n targetContext[prop] = (...args) => {\n const newContext = proxylessContext(targetContext._clone());\n const contextWithRuleApplied = newContext._applyRule(\n ruleSet[prop],\n prop,\n )(...args);\n return contextWithRuleApplied;\n };\n });\n return targetContext;\n };\n\n const contextWithAvailableRules = addRuleSet(availableRules, context);\n const contextWithAllRules = addRuleSet(\n customRules,\n contextWithAvailableRules,\n );\n\n Object.keys(availableModifiers).forEach(prop => {\n Object.defineProperty(contextWithAllRules, prop, {\n get: () => {\n const newContext = proxylessContext(contextWithAllRules._clone());\n return newContext._applyModifier(availableModifiers[prop], prop);\n },\n });\n });\n\n return contextWithAllRules;\n}\n\nconst availableModifiers = {\n not: {\n simple: fn => value => !fn(value),\n async: fn => value =>\n Promise.resolve(fn(value))\n .then(result => !result)\n .catch(() => true),\n },\n\n some: {\n simple: fn => value => {\n return split(value).some(item => {\n try {\n return fn(item);\n } catch (ex) {\n return false;\n }\n });\n },\n async: fn => value => {\n return Promise.all(\n split(value).map(item => {\n try {\n return fn(item).catch(() => false);\n } catch (ex) {\n return false;\n }\n }),\n ).then(result => result.some(Boolean));\n },\n },\n\n every: {\n simple: fn => value => value !== false && split(value).every(fn),\n async: fn => value =>\n Promise.all(split(value).map(fn)).then(result => result.every(Boolean)),\n },\n\n strict: {\n simple: (fn, rule) => value => {\n if (isSchemaRule(rule) && value && typeof value === 'object') {\n return (\n Object.keys(rule.args[0]).length === Object.keys(value).length &&\n fn(value)\n );\n }\n return fn(value);\n },\n async: (fn, rule) => value =>\n Promise.resolve(fn(value))\n .then(result => {\n if (isSchemaRule(rule) && value && typeof value === 'object') {\n return (\n Object.keys(rule.args[0]).length === Object.keys(value).length &&\n result\n );\n }\n return result;\n })\n .catch(() => false),\n },\n};\n\nfunction isSchemaRule(rule) {\n return (\n rule &&\n rule.name === 'schema' &&\n rule.args.length > 0 &&\n typeof rule.args[0] === 'object'\n );\n}\n\nfunction split(value) {\n if (typeof value === 'string') {\n return value.split('');\n }\n return value;\n}\n\nconst availableRules = {\n // Value\n\n equal: expected => value => value == expected,\n\n exact: expected => value => value === expected,\n\n // Types\n\n number: (allowInfinite = true) => value =>\n typeof value === 'number' && (allowInfinite || isFinite(value)),\n\n integer: () => value => {\n const isInteger = Number.isInteger || isIntegerPolyfill;\n return isInteger(value);\n },\n\n numeric: () => value => !isNaN(parseFloat(value)) && isFinite(value),\n\n string: () => testType('string'),\n\n boolean: () => testType('boolean'),\n\n undefined: () => testType('undefined'),\n\n null: () => testType('null'),\n\n array: () => testType('array'),\n\n object: () => testType('object'),\n\n instanceOf: instance => value => value instanceof instance,\n\n // Pattern\n\n pattern: expected => value => expected.test(value),\n\n lowercase: () => value => /^([a-z]+\\s*)+$/.test(value),\n\n uppercase: () => value => /^([A-Z]+\\s*)+$/.test(value),\n\n vowel: () => value => /^[aeiou]+$/i.test(value),\n\n consonant: () => value => /^(?=[^aeiou])([a-z]+)$/i.test(value),\n\n // Value at\n\n first: expected => value => value[0] == expected,\n\n last: expected => value => value[value.length - 1] == expected,\n\n // Length\n\n empty: () => value => value.length === 0,\n\n length: (min, max) => value =>\n value.length >= min && value.length <= (max || min),\n\n minLength: min => value => value.length >= min,\n\n maxLength: max => value => value.length <= max,\n\n // Range\n\n negative: () => value => value < 0,\n\n positive: () => value => value >= 0,\n\n between: (a, b) => value => value >= a && value <= b,\n\n range: (a, b) => value => value >= a && value <= b,\n\n lessThan: n => value => value < n,\n\n lessThanOrEqual: n => value => value <= n,\n\n greaterThan: n => value => value > n,\n\n greaterThanOrEqual: n => value => value >= n,\n\n // Divisible\n\n even: () => value => value % 2 === 0,\n\n odd: () => value => value % 2 !== 0,\n\n includes: expected => value => ~value.indexOf(expected),\n\n schema: schema => testSchema(schema),\n\n // branching\n\n passesAnyOf: (...validations) => value =>\n validations.some(validation => validation.test(value)),\n\n optional: createOptionalRule(false),\n optionalAsync: createOptionalRule(true),\n};\n\nfunction createOptionalRule(asynchronous) {\n return (validation, considerTrimmedEmptyString = false) => value => {\n if (\n considerTrimmedEmptyString &&\n typeof value === 'string' &&\n value.trim() === ''\n ) {\n return true;\n }\n\n if (value !== undefined && value !== null) {\n if (!asynchronous) {\n validation.check(value);\n } else {\n return validation.testAsync(value);\n }\n }\n return true;\n };\n}\n\nfunction testType(expected) {\n return value => {\n return (\n (Array.isArray(value) && expected === 'array') ||\n (value === null && expected === 'null') ||\n typeof value === expected\n );\n };\n}\n\nfunction isIntegerPolyfill(value) {\n return (\n typeof value === 'number' && isFinite(value) && Math.floor(value) === value\n );\n}\n\nfunction testSchema(schema) {\n return {\n simple: value => {\n const causes = [];\n Object.keys(schema).forEach(key => {\n const nestedValidation = schema[key];\n try {\n nestedValidation.check((value || {})[key]);\n } catch (ex) {\n ex.target = key;\n causes.push(ex);\n }\n });\n if (causes.length > 0) {\n throw causes;\n }\n return true;\n },\n async: value => {\n const causes = [];\n const nested = Object.keys(schema).map(key => {\n const nestedValidation = schema[key];\n return nestedValidation.testAsync((value || {})[key]).catch(ex => {\n ex.target = key;\n causes.push(ex);\n });\n });\n return Promise.all(nested).then(() => {\n if (causes.length > 0) {\n throw causes;\n }\n\n return true;\n });\n },\n };\n}\n\nexport default v8n;\n"],"names":["Rule","name","fn","args","modifiers","this","pickFn","variant","testAux","rule","length","const","modifier","shift","nextFn","perform","testAsyncAux","performAsync","value","Promise","resolve","_test","let","slice","ex","_check","it","_testAsync","reject","then","valid","catch","Modifier","ValidationError","cause","target","super","remaining","Error","captureStackTrace","Context","chain","nextRuleModifiers","executeAsyncRules","rules","v8n","undefined","Proxy","proxyContext","proxylessContext","_applyRule","ruleFn","push","apply","_applyModifier","simple","async","_clone","test","every","testAll","err","forEach","check","testAsync","customRules","context","get","obj","prop","newContext","availableModifiers","availableRules","addRuleSet","ruleSet","targetContext","Object","keys","contextWithRuleApplied","contextWithAvailableRules","contextWithAllRules","defineProperty","extend","newRules","assign","clearCustomRules","not","result","some","split","item","all","map","Boolean","strict","isSchemaRule","equal","expected","exact","number","allowInfinite","isFinite","integer","Number","isInteger","isIntegerPolyfill","numeric","isNaN","parseFloat","string","testType","boolean","null","array","object","instanceOf","instance","pattern","lowercase","uppercase","vowel","consonant","first","last","empty","min","max","minLength","maxLength","negative","positive","between","a","b","range","lessThan","n","lessThanOrEqual","greaterThan","greaterThanOrEqual","even","odd","includes","indexOf","schema","causes","key","nestedValidation","nested","testSchema","passesAnyOf","validations","validation","optional","createOptionalRule","optionalAsync","asynchronous","considerTrimmedEmptyString","trim","Array","isArray","Math","floor"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v8n.cjs.js b/dist/v8n.cjs.js index b40d7db..ff3ea1b 100644 --- a/dist/v8n.cjs.js +++ b/dist/v8n.cjs.js @@ -11,13 +11,13 @@ Rule.prototype._test = function _test (value) { var fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = function () { return false; }; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex$1) { return false; } @@ -25,14 +25,14 @@ Rule.prototype._test = function _test (value) { Rule.prototype._check = function _check (value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), function (it) { return it; })(false)) { + if (testAux(this.modifiers.slice(), function (it) { return it; }, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } }; @@ -43,7 +43,8 @@ Rule.prototype._testAsync = function _testAsync (value) { return new Promise(function (resolve, reject) { testAsyncAux( this$1.modifiers.slice(), - this$1.fn + this$1.fn, + this$1 )(value) .then(function (valid) { if (valid) { @@ -62,21 +63,21 @@ function pickFn(fn, variant) { return typeof fn === 'object' ? fn[variant] : fn; } -function testAux(modifiers, fn) { +function testAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + var nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } -function testAsyncAux(modifiers, fn) { +function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + var nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return function (value) { return Promise.resolve(pickFn(fn, 'async')(value)); }; } @@ -304,8 +305,40 @@ var availableModifiers = { simple: function (fn) { return function (value) { return value !== false && split(value).every(fn); }; }, async: function (fn) { return function (value) { return Promise.all(split(value).map(fn)).then(function (result) { return result.every(Boolean); }); }; }, }, + + strict: { + simple: function (fn, rule) { return function (value) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }; }, + async: function (fn, rule) { return function (value) { return Promise.resolve(fn(value)) + .then(function (result) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(function () { return false; }); }; }, + }, }; +function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); +} + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/dist/v8n.esm.browser.js b/dist/v8n.esm.browser.js index ac6f6ee..0dc6270 100644 --- a/dist/v8n.esm.browser.js +++ b/dist/v8n.esm.browser.js @@ -10,13 +10,13 @@ class Rule { let fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = () => false; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { return false; } @@ -24,14 +24,14 @@ class Rule { _check(value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), it => it)(false)) { + if (testAux(this.modifiers.slice(), it => it, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } } @@ -41,6 +41,7 @@ class Rule { testAsyncAux( this.modifiers.slice(), this.fn, + this, )(value) .then(valid => { if (valid) { @@ -58,21 +59,21 @@ function pickFn(fn, variant = 'simple') { return typeof fn === 'object' ? fn[variant] : fn; } -function testAux(modifiers, fn) { +function testAux(modifiers, fn, rule) { if (modifiers.length) { const modifier = modifiers.shift(); - const nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + const nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } -function testAsyncAux(modifiers, fn) { +function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { const modifier = modifiers.shift(); - const nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + const nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return value => Promise.resolve(pickFn(fn, 'async')(value)); } @@ -284,8 +285,41 @@ const availableModifiers = { async: fn => value => Promise.all(split(value).map(fn)).then(result => result.every(Boolean)), }, + + strict: { + simple: (fn, rule) => value => { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }, + async: (fn, rule) => value => + Promise.resolve(fn(value)) + .then(result => { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(() => false), + }, }; +function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); +} + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/dist/v8n.esm.browser.min.js b/dist/v8n.esm.browser.min.js index 441b7bd..78e3502 100644 --- a/dist/v8n.esm.browser.min.js +++ b/dist/v8n.esm.browser.min.js @@ -1,2 +1,2 @@ -class e{constructor(e,t,n,r){this.name=e,this.fn=t,this.args=n,this.modifiers=r}_test(e){let t=this.fn;try{n(this.modifiers.slice(),t)(e)}catch(e){t=()=>!1}try{return n(this.modifiers.slice(),t)(e)}catch(e){return!1}}_check(e){try{n(this.modifiers.slice(),this.fn)(e)}catch(e){if(n(this.modifiers.slice(),(e=>e))(!1))return}if(!n(this.modifiers.slice(),this.fn)(e))throw null}_testAsync(e){return new Promise(((t,n)=>{r(this.modifiers.slice(),this.fn)(e).then((r=>{r?t(e):n(null)})).catch((e=>n(e)))}))}}function t(e,t="simple"){return"object"==typeof e?e[t]:e}function n(e,r){if(e.length){const t=e.shift(),s=n(e,r);return t.perform(s)}return t(r)}function r(e,n){if(e.length){const t=e.shift(),s=r(e,n);return t.performAsync(s)}return e=>Promise.resolve(t(n,"async")(e))}class s{constructor(e,t,n){this.name=e,this.perform=t,this.performAsync=n}}class i extends Error{constructor(e,t,n,r,...s){super(s),Error.captureStackTrace&&Error.captureStackTrace(this,i),this.rule=e,this.value=t,this.cause=n,this.target=r}}class c{constructor(e=[],t=[]){this.chain=e,this.nextRuleModifiers=t}_applyRule(t,n){return(...r)=>(this.chain.push(new e(n,t.apply(this,r),r,this.nextRuleModifiers)),this.nextRuleModifiers=[],this)}_applyModifier(e,t){return this.nextRuleModifiers.push(new s(t,e.simple,e.async)),this}_clone(){return new c(this.chain.slice(),this.nextRuleModifiers.slice())}test(e){return this.chain.every((t=>t._test(e)))}testAll(e){const t=[];return this.chain.forEach((n=>{try{n._check(e)}catch(r){t.push(new i(n,e,r))}})),t}check(e){this.chain.forEach((t=>{try{t._check(e)}catch(n){throw new i(t,e,n)}}))}testAsync(e){return new Promise(((t,n)=>{o(e,this.chain.slice(),t,n)}))}}function o(e,t,n,r){if(t.length){const s=t.shift();s._testAsync(e).then((()=>{o(e,t,n,r)}),(t=>{r(new i(s,e,t))}))}else n(e)}function a(){return void 0!==typeof Proxy?l(new c):u(new c)}let h={};function l(e){return new Proxy(e,{get(t,n){if(n in t)return t[n];const r=l(e._clone());return n in f?r._applyModifier(f[n],n):n in h?r._applyRule(h[n],n):n in y?r._applyRule(y[n],n):void 0}})}function u(e){const t=(e,t)=>(Object.keys(e).forEach((n=>{t[n]=(...r)=>u(t._clone())._applyRule(e[n],n)(...r)})),t),n=t(y,e),r=t(h,n);return Object.keys(f).forEach((e=>{Object.defineProperty(r,e,{get:()=>u(r._clone())._applyModifier(f[e],e)})})),r}a.extend=function(e){Object.assign(h,e)},a.clearCustomRules=function(){h={}};const f={not:{simple:e=>t=>!e(t),async:e=>t=>Promise.resolve(e(t)).then((e=>!e)).catch((()=>!0))},some:{simple:e=>t=>p(t).some((t=>{try{return e(t)}catch(e){return!1}})),async:e=>t=>Promise.all(p(t).map((t=>{try{return e(t).catch((()=>!1))}catch(e){return!1}}))).then((e=>e.some(Boolean)))},every:{simple:e=>t=>!1!==t&&p(t).every(e),async:e=>t=>Promise.all(p(t).map(e)).then((e=>e.every(Boolean)))}};function p(e){return"string"==typeof e?e.split(""):e}const y={equal:e=>t=>t==e,exact:e=>t=>t===e,number:(e=!0)=>t=>"number"==typeof t&&(e||isFinite(t)),integer:()=>e=>(Number.isInteger||d)(e),numeric:()=>e=>!isNaN(parseFloat(e))&&isFinite(e),string:()=>g("string"),boolean:()=>g("boolean"),undefined:()=>g("undefined"),null:()=>g("null"),array:()=>g("array"),object:()=>g("object"),instanceOf:e=>t=>t instanceof e,pattern:e=>t=>e.test(t),lowercase:()=>e=>/^([a-z]+\s*)+$/.test(e),uppercase:()=>e=>/^([A-Z]+\s*)+$/.test(e),vowel:()=>e=>/^[aeiou]+$/i.test(e),consonant:()=>e=>/^(?=[^aeiou])([a-z]+)$/i.test(e),first:e=>t=>t[0]==e,last:e=>t=>t[t.length-1]==e,empty:()=>e=>0===e.length,length:(e,t)=>n=>n.length>=e&&n.length<=(t||e),minLength:e=>t=>t.length>=e,maxLength:e=>t=>t.length<=e,negative:()=>e=>e<0,positive:()=>e=>e>=0,between:(e,t)=>n=>n>=e&&n<=t,range:(e,t)=>n=>n>=e&&n<=t,lessThan:e=>t=>tt=>t<=e,greaterThan:e=>t=>t>e,greaterThanOrEqual:e=>t=>t>=e,even:()=>e=>e%2==0,odd:()=>e=>e%2!=0,includes:e=>t=>~t.indexOf(e),schema:e=>function(e){return{simple:t=>{const n=[];if(Object.keys(e).forEach((r=>{const s=e[r];try{s.check((t||{})[r])}catch(e){e.target=r,n.push(e)}})),n.length>0)throw n;return!0},async:t=>{const n=[],r=Object.keys(e).map((r=>e[r].testAsync((t||{})[r]).catch((e=>{e.target=r,n.push(e)}))));return Promise.all(r).then((()=>{if(n.length>0)throw n;return!0}))}}}(e),passesAnyOf:(...e)=>t=>e.some((e=>e.test(t))),optional:m(!1),optionalAsync:m(!0)};function m(e){return(t,n=!1)=>r=>{if(n&&"string"==typeof r&&""===r.trim())return!0;if(null!=r){if(e)return t.testAsync(r);t.check(r)}return!0}}function g(e){return t=>Array.isArray(t)&&"array"===e||null===t&&"null"===e||typeof t===e}function d(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}export default a; +class e{constructor(e,t,n,s){this.name=e,this.fn=t,this.args=n,this.modifiers=s}_test(e){let t=this.fn;try{n(this.modifiers.slice(),t,this)(e)}catch(e){t=()=>!1}try{return n(this.modifiers.slice(),t,this)(e)}catch(e){return!1}}_check(e){try{n(this.modifiers.slice(),this.fn,this)(e)}catch(e){if(n(this.modifiers.slice(),(e=>e),this)(!1))return}if(!n(this.modifiers.slice(),this.fn,this)(e))throw null}_testAsync(e){return new Promise(((t,n)=>{s(this.modifiers.slice(),this.fn,this)(e).then((s=>{s?t(e):n(null)})).catch((e=>n(e)))}))}}function t(e,t="simple"){return"object"==typeof e?e[t]:e}function n(e,s,r){if(e.length){const t=e.shift(),i=n(e,s,r);return t.perform(i,r)}return t(s)}function s(e,n,r){if(e.length){const t=e.shift(),i=s(e,n,r);return t.performAsync(i,r)}return e=>Promise.resolve(t(n,"async")(e))}class r{constructor(e,t,n){this.name=e,this.perform=t,this.performAsync=n}}class i extends Error{constructor(e,t,n,s,...r){super(r),Error.captureStackTrace&&Error.captureStackTrace(this,i),this.rule=e,this.value=t,this.cause=n,this.target=s}}class c{constructor(e=[],t=[]){this.chain=e,this.nextRuleModifiers=t}_applyRule(t,n){return(...s)=>(this.chain.push(new e(n,t.apply(this,s),s,this.nextRuleModifiers)),this.nextRuleModifiers=[],this)}_applyModifier(e,t){return this.nextRuleModifiers.push(new r(t,e.simple,e.async)),this}_clone(){return new c(this.chain.slice(),this.nextRuleModifiers.slice())}test(e){return this.chain.every((t=>t._test(e)))}testAll(e){const t=[];return this.chain.forEach((n=>{try{n._check(e)}catch(s){t.push(new i(n,e,s))}})),t}check(e){this.chain.forEach((t=>{try{t._check(e)}catch(n){throw new i(t,e,n)}}))}testAsync(e){return new Promise(((t,n)=>{o(e,this.chain.slice(),t,n)}))}}function o(e,t,n,s){if(t.length){const r=t.shift();r._testAsync(e).then((()=>{o(e,t,n,s)}),(t=>{s(new i(r,e,t))}))}else n(e)}function h(){return void 0!==typeof Proxy?l(new c):u(new c)}let a={};function l(e){return new Proxy(e,{get(t,n){if(n in t)return t[n];const s=l(e._clone());return n in f?s._applyModifier(f[n],n):n in a?s._applyRule(a[n],n):n in m?s._applyRule(m[n],n):void 0}})}function u(e){const t=(e,t)=>(Object.keys(e).forEach((n=>{t[n]=(...s)=>u(t._clone())._applyRule(e[n],n)(...s)})),t),n=t(m,e),s=t(a,n);return Object.keys(f).forEach((e=>{Object.defineProperty(s,e,{get:()=>u(s._clone())._applyModifier(f[e],e)})})),s}h.extend=function(e){Object.assign(a,e)},h.clearCustomRules=function(){a={}};const f={not:{simple:e=>t=>!e(t),async:e=>t=>Promise.resolve(e(t)).then((e=>!e)).catch((()=>!0))},some:{simple:e=>t=>p(t).some((t=>{try{return e(t)}catch(e){return!1}})),async:e=>t=>Promise.all(p(t).map((t=>{try{return e(t).catch((()=>!1))}catch(e){return!1}}))).then((e=>e.some(Boolean)))},every:{simple:e=>t=>!1!==t&&p(t).every(e),async:e=>t=>Promise.all(p(t).map(e)).then((e=>e.every(Boolean)))},strict:{simple:(e,t)=>n=>y(t)&&n&&"object"==typeof n?Object.keys(t.args[0]).length===Object.keys(n).length&&e(n):e(n),async:(e,t)=>n=>Promise.resolve(e(n)).then((e=>y(t)&&n&&"object"==typeof n?Object.keys(t.args[0]).length===Object.keys(n).length&&e:e)).catch((()=>!1))}};function y(e){return e&&"schema"===e.name&&e.args.length>0&&"object"==typeof e.args[0]}function p(e){return"string"==typeof e?e.split(""):e}const m={equal:e=>t=>t==e,exact:e=>t=>t===e,number:(e=!0)=>t=>"number"==typeof t&&(e||isFinite(t)),integer:()=>e=>(Number.isInteger||b)(e),numeric:()=>e=>!isNaN(parseFloat(e))&&isFinite(e),string:()=>d("string"),boolean:()=>d("boolean"),undefined:()=>d("undefined"),null:()=>d("null"),array:()=>d("array"),object:()=>d("object"),instanceOf:e=>t=>t instanceof e,pattern:e=>t=>e.test(t),lowercase:()=>e=>/^([a-z]+\s*)+$/.test(e),uppercase:()=>e=>/^([A-Z]+\s*)+$/.test(e),vowel:()=>e=>/^[aeiou]+$/i.test(e),consonant:()=>e=>/^(?=[^aeiou])([a-z]+)$/i.test(e),first:e=>t=>t[0]==e,last:e=>t=>t[t.length-1]==e,empty:()=>e=>0===e.length,length:(e,t)=>n=>n.length>=e&&n.length<=(t||e),minLength:e=>t=>t.length>=e,maxLength:e=>t=>t.length<=e,negative:()=>e=>e<0,positive:()=>e=>e>=0,between:(e,t)=>n=>n>=e&&n<=t,range:(e,t)=>n=>n>=e&&n<=t,lessThan:e=>t=>tt=>t<=e,greaterThan:e=>t=>t>e,greaterThanOrEqual:e=>t=>t>=e,even:()=>e=>e%2==0,odd:()=>e=>e%2!=0,includes:e=>t=>~t.indexOf(e),schema:e=>function(e){return{simple:t=>{const n=[];if(Object.keys(e).forEach((s=>{const r=e[s];try{r.check((t||{})[s])}catch(e){e.target=s,n.push(e)}})),n.length>0)throw n;return!0},async:t=>{const n=[],s=Object.keys(e).map((s=>e[s].testAsync((t||{})[s]).catch((e=>{e.target=s,n.push(e)}))));return Promise.all(s).then((()=>{if(n.length>0)throw n;return!0}))}}}(e),passesAnyOf:(...e)=>t=>e.some((e=>e.test(t))),optional:g(!1),optionalAsync:g(!0)};function g(e){return(t,n=!1)=>s=>{if(n&&"string"==typeof s&&""===s.trim())return!0;if(null!=s){if(e)return t.testAsync(s);t.check(s)}return!0}}function d(e){return t=>Array.isArray(t)&&"array"===e||null===t&&"null"===e||typeof t===e}function b(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}export default h; //# sourceMappingURL=v8n.esm.browser.min.js.map diff --git a/dist/v8n.esm.browser.min.js.map b/dist/v8n.esm.browser.min.js.map index b17bd18..25258a5 100644 --- a/dist/v8n.esm.browser.min.js.map +++ b/dist/v8n.esm.browser.min.js.map @@ -1 +1 @@ -{"version":3,"file":"v8n.esm.browser.min.js","sources":["../src/Rule.js","../src/Modifier.js","../src/ValidationError.js","../src/Context.js","../src/v8n.js"],"sourcesContent":["class Rule {\r\n constructor(name, fn, args, modifiers) {\r\n this.name = name;\r\n this.fn = fn;\r\n this.args = args;\r\n this.modifiers = modifiers;\r\n }\r\n\r\n _test(value) {\r\n let fn = this.fn;\r\n\r\n try {\r\n testAux(this.modifiers.slice(), fn)(value);\r\n } catch (ex) {\r\n fn = () => false;\r\n }\r\n\r\n try {\r\n return testAux(this.modifiers.slice(), fn)(value);\r\n } catch (ex) {\r\n return false;\r\n }\r\n }\r\n\r\n _check(value) {\r\n try {\r\n testAux(this.modifiers.slice(), this.fn)(value);\r\n } catch (ex) {\r\n if (testAux(this.modifiers.slice(), it => it)(false)) {\r\n return;\r\n }\r\n }\r\n\r\n if (!testAux(this.modifiers.slice(), this.fn)(value)) {\r\n throw null;\r\n }\r\n }\r\n\r\n _testAsync(value) {\r\n return new Promise((resolve, reject) => {\r\n testAsyncAux(\r\n this.modifiers.slice(),\r\n this.fn,\r\n )(value)\r\n .then(valid => {\r\n if (valid) {\r\n resolve(value);\r\n } else {\r\n reject(null);\r\n }\r\n })\r\n .catch(ex => reject(ex));\r\n });\r\n }\r\n}\r\n\r\nfunction pickFn(fn, variant = 'simple') {\r\n return typeof fn === 'object' ? fn[variant] : fn;\r\n}\r\n\r\nfunction testAux(modifiers, fn) {\r\n if (modifiers.length) {\r\n const modifier = modifiers.shift();\r\n const nextFn = testAux(modifiers, fn);\r\n return modifier.perform(nextFn);\r\n } else {\r\n return pickFn(fn);\r\n }\r\n}\r\n\r\nfunction testAsyncAux(modifiers, fn) {\r\n if (modifiers.length) {\r\n const modifier = modifiers.shift();\r\n const nextFn = testAsyncAux(modifiers, fn);\r\n return modifier.performAsync(nextFn);\r\n } else {\r\n return value => Promise.resolve(pickFn(fn, 'async')(value));\r\n }\r\n}\r\n\r\nexport default Rule;\r\n","class Modifier {\r\n constructor(name, perform, performAsync) {\r\n this.name = name;\r\n this.perform = perform;\r\n this.performAsync = performAsync;\r\n }\r\n}\r\n\r\nexport default Modifier;\r\n","class ValidationError extends Error {\r\n constructor(rule, value, cause, target, ...remaining) {\r\n super(remaining);\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, ValidationError);\r\n }\r\n this.rule = rule;\r\n this.value = value;\r\n this.cause = cause;\r\n this.target = target;\r\n }\r\n}\r\n\r\nexport default ValidationError;\r\n","import Rule from './Rule';\r\nimport Modifier from './Modifier';\r\nimport ValidationError from './ValidationError';\r\n\r\nclass Context {\r\n constructor(chain = [], nextRuleModifiers = []) {\r\n this.chain = chain;\r\n this.nextRuleModifiers = nextRuleModifiers;\r\n }\r\n\r\n _applyRule(ruleFn, name) {\r\n return (...args) => {\r\n this.chain.push(\r\n new Rule(name, ruleFn.apply(this, args), args, this.nextRuleModifiers),\r\n );\r\n this.nextRuleModifiers = [];\r\n return this;\r\n };\r\n }\r\n\r\n _applyModifier(modifier, name) {\r\n this.nextRuleModifiers.push(\r\n new Modifier(name, modifier.simple, modifier.async),\r\n );\r\n return this;\r\n }\r\n\r\n _clone() {\r\n return new Context(this.chain.slice(), this.nextRuleModifiers.slice());\r\n }\r\n\r\n test(value) {\r\n return this.chain.every(rule => rule._test(value));\r\n }\r\n\r\n testAll(value) {\r\n const err = [];\r\n this.chain.forEach(rule => {\r\n try {\r\n rule._check(value);\r\n } catch (ex) {\r\n err.push(new ValidationError(rule, value, ex));\r\n }\r\n });\r\n return err;\r\n }\r\n\r\n check(value) {\r\n this.chain.forEach(rule => {\r\n try {\r\n rule._check(value);\r\n } catch (ex) {\r\n throw new ValidationError(rule, value, ex);\r\n }\r\n });\r\n }\r\n\r\n testAsync(value) {\r\n return new Promise((resolve, reject) => {\r\n executeAsyncRules(value, this.chain.slice(), resolve, reject);\r\n });\r\n }\r\n}\r\n\r\nfunction executeAsyncRules(value, rules, resolve, reject) {\r\n if (rules.length) {\r\n const rule = rules.shift();\r\n rule._testAsync(value).then(\r\n () => {\r\n executeAsyncRules(value, rules, resolve, reject);\r\n },\r\n cause => {\r\n reject(new ValidationError(rule, value, cause));\r\n },\r\n );\r\n } else {\r\n resolve(value);\r\n }\r\n}\r\n\r\nexport default Context;\r\n","import Context from './Context';\r\n\r\nfunction v8n() {\r\n return typeof Proxy !== undefined\r\n ? proxyContext(new Context())\r\n : proxylessContext(new Context());\r\n}\r\n\r\n// Custom rules\r\nlet customRules = {};\r\n\r\nv8n.extend = function(newRules) {\r\n Object.assign(customRules, newRules);\r\n};\r\n\r\nv8n.clearCustomRules = function() {\r\n customRules = {};\r\n};\r\n\r\nfunction proxyContext(context) {\r\n return new Proxy(context, {\r\n get(obj, prop) {\r\n if (prop in obj) {\r\n return obj[prop];\r\n }\r\n\r\n const newContext = proxyContext(context._clone());\r\n\r\n if (prop in availableModifiers) {\r\n return newContext._applyModifier(availableModifiers[prop], prop);\r\n }\r\n if (prop in customRules) {\r\n return newContext._applyRule(customRules[prop], prop);\r\n }\r\n if (prop in availableRules) {\r\n return newContext._applyRule(availableRules[prop], prop);\r\n }\r\n },\r\n });\r\n}\r\n\r\nfunction proxylessContext(context) {\r\n const addRuleSet = (ruleSet, targetContext) => {\r\n Object.keys(ruleSet).forEach(prop => {\r\n targetContext[prop] = (...args) => {\r\n const newContext = proxylessContext(targetContext._clone());\r\n const contextWithRuleApplied = newContext._applyRule(\r\n ruleSet[prop],\r\n prop,\r\n )(...args);\r\n return contextWithRuleApplied;\r\n };\r\n });\r\n return targetContext;\r\n };\r\n\r\n const contextWithAvailableRules = addRuleSet(availableRules, context);\r\n const contextWithAllRules = addRuleSet(\r\n customRules,\r\n contextWithAvailableRules,\r\n );\r\n\r\n Object.keys(availableModifiers).forEach(prop => {\r\n Object.defineProperty(contextWithAllRules, prop, {\r\n get: () => {\r\n const newContext = proxylessContext(contextWithAllRules._clone());\r\n return newContext._applyModifier(availableModifiers[prop], prop);\r\n },\r\n });\r\n });\r\n\r\n return contextWithAllRules;\r\n}\r\n\r\nconst availableModifiers = {\r\n not: {\r\n simple: fn => value => !fn(value),\r\n async: fn => value =>\r\n Promise.resolve(fn(value))\r\n .then(result => !result)\r\n .catch(() => true),\r\n },\r\n\r\n some: {\r\n simple: fn => value => {\r\n return split(value).some(item => {\r\n try {\r\n return fn(item);\r\n } catch (ex) {\r\n return false;\r\n }\r\n });\r\n },\r\n async: fn => value => {\r\n return Promise.all(\r\n split(value).map(item => {\r\n try {\r\n return fn(item).catch(() => false);\r\n } catch (ex) {\r\n return false;\r\n }\r\n }),\r\n ).then(result => result.some(Boolean));\r\n },\r\n },\r\n\r\n every: {\r\n simple: fn => value => value !== false && split(value).every(fn),\r\n async: fn => value =>\r\n Promise.all(split(value).map(fn)).then(result => result.every(Boolean)),\r\n },\r\n};\r\n\r\nfunction split(value) {\r\n if (typeof value === 'string') {\r\n return value.split('');\r\n }\r\n return value;\r\n}\r\n\r\nconst availableRules = {\r\n // Value\r\n\r\n equal: expected => value => value == expected,\r\n\r\n exact: expected => value => value === expected,\r\n\r\n // Types\r\n\r\n number: (allowInfinite = true) => value =>\r\n typeof value === 'number' && (allowInfinite || isFinite(value)),\r\n\r\n integer: () => value => {\r\n const isInteger = Number.isInteger || isIntegerPolyfill;\r\n return isInteger(value);\r\n },\r\n\r\n numeric: () => value => !isNaN(parseFloat(value)) && isFinite(value),\r\n\r\n string: () => testType('string'),\r\n\r\n boolean: () => testType('boolean'),\r\n\r\n undefined: () => testType('undefined'),\r\n\r\n null: () => testType('null'),\r\n\r\n array: () => testType('array'),\r\n\r\n object: () => testType('object'),\r\n\r\n instanceOf: instance => value => value instanceof instance,\r\n\r\n // Pattern\r\n\r\n pattern: expected => value => expected.test(value),\r\n\r\n lowercase: () => value => /^([a-z]+\\s*)+$/.test(value),\r\n\r\n uppercase: () => value => /^([A-Z]+\\s*)+$/.test(value),\r\n\r\n vowel: () => value => /^[aeiou]+$/i.test(value),\r\n\r\n consonant: () => value => /^(?=[^aeiou])([a-z]+)$/i.test(value),\r\n\r\n // Value at\r\n\r\n first: expected => value => value[0] == expected,\r\n\r\n last: expected => value => value[value.length - 1] == expected,\r\n\r\n // Length\r\n\r\n empty: () => value => value.length === 0,\r\n\r\n length: (min, max) => value =>\r\n value.length >= min && value.length <= (max || min),\r\n\r\n minLength: min => value => value.length >= min,\r\n\r\n maxLength: max => value => value.length <= max,\r\n\r\n // Range\r\n\r\n negative: () => value => value < 0,\r\n\r\n positive: () => value => value >= 0,\r\n\r\n between: (a, b) => value => value >= a && value <= b,\r\n\r\n range: (a, b) => value => value >= a && value <= b,\r\n\r\n lessThan: n => value => value < n,\r\n\r\n lessThanOrEqual: n => value => value <= n,\r\n\r\n greaterThan: n => value => value > n,\r\n\r\n greaterThanOrEqual: n => value => value >= n,\r\n\r\n // Divisible\r\n\r\n even: () => value => value % 2 === 0,\r\n\r\n odd: () => value => value % 2 !== 0,\r\n\r\n includes: expected => value => ~value.indexOf(expected),\r\n\r\n schema: schema => testSchema(schema),\r\n\r\n // branching\r\n\r\n passesAnyOf: (...validations) => value =>\r\n validations.some(validation => validation.test(value)),\r\n\r\n optional: createOptionalRule(false),\r\n optionalAsync: createOptionalRule(true),\r\n};\r\n\r\nfunction createOptionalRule(asynchronous) {\r\n return (validation, considerTrimmedEmptyString = false) => value => {\r\n if (\r\n considerTrimmedEmptyString &&\r\n typeof value === 'string' &&\r\n value.trim() === ''\r\n ) {\r\n return true;\r\n }\r\n\r\n if (value !== undefined && value !== null) {\r\n if (!asynchronous) {\r\n validation.check(value);\r\n } else {\r\n return validation.testAsync(value);\r\n }\r\n }\r\n return true;\r\n };\r\n}\r\n\r\nfunction testType(expected) {\r\n return value => {\r\n return (\r\n (Array.isArray(value) && expected === 'array') ||\r\n (value === null && expected === 'null') ||\r\n typeof value === expected\r\n );\r\n };\r\n}\r\n\r\nfunction isIntegerPolyfill(value) {\r\n return (\r\n typeof value === 'number' && isFinite(value) && Math.floor(value) === value\r\n );\r\n}\r\n\r\nfunction testSchema(schema) {\r\n return {\r\n simple: value => {\r\n const causes = [];\r\n Object.keys(schema).forEach(key => {\r\n const nestedValidation = schema[key];\r\n try {\r\n nestedValidation.check((value || {})[key]);\r\n } catch (ex) {\r\n ex.target = key;\r\n causes.push(ex);\r\n }\r\n });\r\n if (causes.length > 0) {\r\n throw causes;\r\n }\r\n return true;\r\n },\r\n async: value => {\r\n const causes = [];\r\n const nested = Object.keys(schema).map(key => {\r\n const nestedValidation = schema[key];\r\n return nestedValidation.testAsync((value || {})[key]).catch(ex => {\r\n ex.target = key;\r\n causes.push(ex);\r\n });\r\n });\r\n return Promise.all(nested).then(() => {\r\n if (causes.length > 0) {\r\n throw causes;\r\n }\r\n\r\n return true;\r\n });\r\n },\r\n };\r\n}\r\n\r\nexport default v8n;\r\n"],"names":["Rule","[object Object]","name","fn","args","modifiers","this","value","testAux","slice","ex","it","Promise","resolve","reject","testAsyncAux","then","valid","catch","pickFn","variant","length","modifier","shift","nextFn","perform","performAsync","Modifier","ValidationError","Error","rule","cause","target","remaining","super","captureStackTrace","Context","chain","nextRuleModifiers","ruleFn","push","apply","simple","async","every","_test","err","forEach","_check","executeAsyncRules","rules","_testAsync","v8n","undefined","Proxy","proxyContext","proxylessContext","customRules","context","obj","prop","newContext","_clone","availableModifiers","_applyModifier","_applyRule","availableRules","addRuleSet","ruleSet","targetContext","Object","keys","contextWithAvailableRules","contextWithAllRules","defineProperty","get","extend","newRules","assign","clearCustomRules","not","result","some","split","item","all","map","Boolean","equal","expected","exact","number","allowInfinite","isFinite","integer","Number","isInteger","isIntegerPolyfill","numeric","isNaN","parseFloat","string","testType","boolean","null","array","object","instanceOf","instance","pattern","test","lowercase","uppercase","vowel","consonant","first","last","empty","min","max","minLength","maxLength","negative","positive","between","a","b","range","lessThan","n","lessThanOrEqual","greaterThan","greaterThanOrEqual","even","odd","includes","indexOf","schema","causes","key","nestedValidation","check","nested","testAsync","testSchema","passesAnyOf","validations","validation","optional","createOptionalRule","optionalAsync","asynchronous","considerTrimmedEmptyString","trim","Array","isArray","Math","floor"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"v8n.esm.browser.min.js","sources":["../src/Rule.js","../src/Modifier.js","../src/ValidationError.js","../src/Context.js","../src/v8n.js"],"sourcesContent":["class Rule {\n constructor(name, fn, args, modifiers) {\n this.name = name;\n this.fn = fn;\n this.args = args;\n this.modifiers = modifiers;\n }\n\n _test(value) {\n let fn = this.fn;\n\n try {\n testAux(this.modifiers.slice(), fn, this)(value);\n } catch (ex) {\n fn = () => false;\n }\n\n try {\n return testAux(this.modifiers.slice(), fn, this)(value);\n } catch (ex) {\n return false;\n }\n }\n\n _check(value) {\n try {\n testAux(this.modifiers.slice(), this.fn, this)(value);\n } catch (ex) {\n if (testAux(this.modifiers.slice(), it => it, this)(false)) {\n return;\n }\n }\n\n if (!testAux(this.modifiers.slice(), this.fn, this)(value)) {\n throw null;\n }\n }\n\n _testAsync(value) {\n return new Promise((resolve, reject) => {\n testAsyncAux(\n this.modifiers.slice(),\n this.fn,\n this,\n )(value)\n .then(valid => {\n if (valid) {\n resolve(value);\n } else {\n reject(null);\n }\n })\n .catch(ex => reject(ex));\n });\n }\n}\n\nfunction pickFn(fn, variant = 'simple') {\n return typeof fn === 'object' ? fn[variant] : fn;\n}\n\nfunction testAux(modifiers, fn, rule) {\n if (modifiers.length) {\n const modifier = modifiers.shift();\n const nextFn = testAux(modifiers, fn, rule);\n return modifier.perform(nextFn, rule);\n } else {\n return pickFn(fn);\n }\n}\n\nfunction testAsyncAux(modifiers, fn, rule) {\n if (modifiers.length) {\n const modifier = modifiers.shift();\n const nextFn = testAsyncAux(modifiers, fn, rule);\n return modifier.performAsync(nextFn, rule);\n } else {\n return value => Promise.resolve(pickFn(fn, 'async')(value));\n }\n}\n\nexport default Rule;\n","class Modifier {\n constructor(name, perform, performAsync) {\n this.name = name;\n this.perform = perform;\n this.performAsync = performAsync;\n }\n}\n\nexport default Modifier;\n","class ValidationError extends Error {\n constructor(rule, value, cause, target, ...remaining) {\n super(remaining);\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n this.rule = rule;\n this.value = value;\n this.cause = cause;\n this.target = target;\n }\n}\n\nexport default ValidationError;\n","import Rule from './Rule';\nimport Modifier from './Modifier';\nimport ValidationError from './ValidationError';\n\nclass Context {\n constructor(chain = [], nextRuleModifiers = []) {\n this.chain = chain;\n this.nextRuleModifiers = nextRuleModifiers;\n }\n\n _applyRule(ruleFn, name) {\n return (...args) => {\n this.chain.push(\n new Rule(name, ruleFn.apply(this, args), args, this.nextRuleModifiers),\n );\n this.nextRuleModifiers = [];\n return this;\n };\n }\n\n _applyModifier(modifier, name) {\n this.nextRuleModifiers.push(\n new Modifier(name, modifier.simple, modifier.async),\n );\n return this;\n }\n\n _clone() {\n return new Context(this.chain.slice(), this.nextRuleModifiers.slice());\n }\n\n test(value) {\n return this.chain.every(rule => rule._test(value));\n }\n\n testAll(value) {\n const err = [];\n this.chain.forEach(rule => {\n try {\n rule._check(value);\n } catch (ex) {\n err.push(new ValidationError(rule, value, ex));\n }\n });\n return err;\n }\n\n check(value) {\n this.chain.forEach(rule => {\n try {\n rule._check(value);\n } catch (ex) {\n throw new ValidationError(rule, value, ex);\n }\n });\n }\n\n testAsync(value) {\n return new Promise((resolve, reject) => {\n executeAsyncRules(value, this.chain.slice(), resolve, reject);\n });\n }\n}\n\nfunction executeAsyncRules(value, rules, resolve, reject) {\n if (rules.length) {\n const rule = rules.shift();\n rule._testAsync(value).then(\n () => {\n executeAsyncRules(value, rules, resolve, reject);\n },\n cause => {\n reject(new ValidationError(rule, value, cause));\n },\n );\n } else {\n resolve(value);\n }\n}\n\nexport default Context;\n","import Context from './Context';\n\nfunction v8n() {\n return typeof Proxy !== undefined\n ? proxyContext(new Context())\n : proxylessContext(new Context());\n}\n\n// Custom rules\nlet customRules = {};\n\nv8n.extend = function(newRules) {\n Object.assign(customRules, newRules);\n};\n\nv8n.clearCustomRules = function() {\n customRules = {};\n};\n\nfunction proxyContext(context) {\n return new Proxy(context, {\n get(obj, prop) {\n if (prop in obj) {\n return obj[prop];\n }\n\n const newContext = proxyContext(context._clone());\n\n if (prop in availableModifiers) {\n return newContext._applyModifier(availableModifiers[prop], prop);\n }\n if (prop in customRules) {\n return newContext._applyRule(customRules[prop], prop);\n }\n if (prop in availableRules) {\n return newContext._applyRule(availableRules[prop], prop);\n }\n },\n });\n}\n\nfunction proxylessContext(context) {\n const addRuleSet = (ruleSet, targetContext) => {\n Object.keys(ruleSet).forEach(prop => {\n targetContext[prop] = (...args) => {\n const newContext = proxylessContext(targetContext._clone());\n const contextWithRuleApplied = newContext._applyRule(\n ruleSet[prop],\n prop,\n )(...args);\n return contextWithRuleApplied;\n };\n });\n return targetContext;\n };\n\n const contextWithAvailableRules = addRuleSet(availableRules, context);\n const contextWithAllRules = addRuleSet(\n customRules,\n contextWithAvailableRules,\n );\n\n Object.keys(availableModifiers).forEach(prop => {\n Object.defineProperty(contextWithAllRules, prop, {\n get: () => {\n const newContext = proxylessContext(contextWithAllRules._clone());\n return newContext._applyModifier(availableModifiers[prop], prop);\n },\n });\n });\n\n return contextWithAllRules;\n}\n\nconst availableModifiers = {\n not: {\n simple: fn => value => !fn(value),\n async: fn => value =>\n Promise.resolve(fn(value))\n .then(result => !result)\n .catch(() => true),\n },\n\n some: {\n simple: fn => value => {\n return split(value).some(item => {\n try {\n return fn(item);\n } catch (ex) {\n return false;\n }\n });\n },\n async: fn => value => {\n return Promise.all(\n split(value).map(item => {\n try {\n return fn(item).catch(() => false);\n } catch (ex) {\n return false;\n }\n }),\n ).then(result => result.some(Boolean));\n },\n },\n\n every: {\n simple: fn => value => value !== false && split(value).every(fn),\n async: fn => value =>\n Promise.all(split(value).map(fn)).then(result => result.every(Boolean)),\n },\n\n strict: {\n simple: (fn, rule) => value => {\n if (isSchemaRule(rule) && value && typeof value === 'object') {\n return (\n Object.keys(rule.args[0]).length === Object.keys(value).length &&\n fn(value)\n );\n }\n return fn(value);\n },\n async: (fn, rule) => value =>\n Promise.resolve(fn(value))\n .then(result => {\n if (isSchemaRule(rule) && value && typeof value === 'object') {\n return (\n Object.keys(rule.args[0]).length === Object.keys(value).length &&\n result\n );\n }\n return result;\n })\n .catch(() => false),\n },\n};\n\nfunction isSchemaRule(rule) {\n return (\n rule &&\n rule.name === 'schema' &&\n rule.args.length > 0 &&\n typeof rule.args[0] === 'object'\n );\n}\n\nfunction split(value) {\n if (typeof value === 'string') {\n return value.split('');\n }\n return value;\n}\n\nconst availableRules = {\n // Value\n\n equal: expected => value => value == expected,\n\n exact: expected => value => value === expected,\n\n // Types\n\n number: (allowInfinite = true) => value =>\n typeof value === 'number' && (allowInfinite || isFinite(value)),\n\n integer: () => value => {\n const isInteger = Number.isInteger || isIntegerPolyfill;\n return isInteger(value);\n },\n\n numeric: () => value => !isNaN(parseFloat(value)) && isFinite(value),\n\n string: () => testType('string'),\n\n boolean: () => testType('boolean'),\n\n undefined: () => testType('undefined'),\n\n null: () => testType('null'),\n\n array: () => testType('array'),\n\n object: () => testType('object'),\n\n instanceOf: instance => value => value instanceof instance,\n\n // Pattern\n\n pattern: expected => value => expected.test(value),\n\n lowercase: () => value => /^([a-z]+\\s*)+$/.test(value),\n\n uppercase: () => value => /^([A-Z]+\\s*)+$/.test(value),\n\n vowel: () => value => /^[aeiou]+$/i.test(value),\n\n consonant: () => value => /^(?=[^aeiou])([a-z]+)$/i.test(value),\n\n // Value at\n\n first: expected => value => value[0] == expected,\n\n last: expected => value => value[value.length - 1] == expected,\n\n // Length\n\n empty: () => value => value.length === 0,\n\n length: (min, max) => value =>\n value.length >= min && value.length <= (max || min),\n\n minLength: min => value => value.length >= min,\n\n maxLength: max => value => value.length <= max,\n\n // Range\n\n negative: () => value => value < 0,\n\n positive: () => value => value >= 0,\n\n between: (a, b) => value => value >= a && value <= b,\n\n range: (a, b) => value => value >= a && value <= b,\n\n lessThan: n => value => value < n,\n\n lessThanOrEqual: n => value => value <= n,\n\n greaterThan: n => value => value > n,\n\n greaterThanOrEqual: n => value => value >= n,\n\n // Divisible\n\n even: () => value => value % 2 === 0,\n\n odd: () => value => value % 2 !== 0,\n\n includes: expected => value => ~value.indexOf(expected),\n\n schema: schema => testSchema(schema),\n\n // branching\n\n passesAnyOf: (...validations) => value =>\n validations.some(validation => validation.test(value)),\n\n optional: createOptionalRule(false),\n optionalAsync: createOptionalRule(true),\n};\n\nfunction createOptionalRule(asynchronous) {\n return (validation, considerTrimmedEmptyString = false) => value => {\n if (\n considerTrimmedEmptyString &&\n typeof value === 'string' &&\n value.trim() === ''\n ) {\n return true;\n }\n\n if (value !== undefined && value !== null) {\n if (!asynchronous) {\n validation.check(value);\n } else {\n return validation.testAsync(value);\n }\n }\n return true;\n };\n}\n\nfunction testType(expected) {\n return value => {\n return (\n (Array.isArray(value) && expected === 'array') ||\n (value === null && expected === 'null') ||\n typeof value === expected\n );\n };\n}\n\nfunction isIntegerPolyfill(value) {\n return (\n typeof value === 'number' && isFinite(value) && Math.floor(value) === value\n );\n}\n\nfunction testSchema(schema) {\n return {\n simple: value => {\n const causes = [];\n Object.keys(schema).forEach(key => {\n const nestedValidation = schema[key];\n try {\n nestedValidation.check((value || {})[key]);\n } catch (ex) {\n ex.target = key;\n causes.push(ex);\n }\n });\n if (causes.length > 0) {\n throw causes;\n }\n return true;\n },\n async: value => {\n const causes = [];\n const nested = Object.keys(schema).map(key => {\n const nestedValidation = schema[key];\n return nestedValidation.testAsync((value || {})[key]).catch(ex => {\n ex.target = key;\n causes.push(ex);\n });\n });\n return Promise.all(nested).then(() => {\n if (causes.length > 0) {\n throw causes;\n }\n\n return true;\n });\n },\n };\n}\n\nexport default v8n;\n"],"names":["Rule","[object Object]","name","fn","args","modifiers","this","value","testAux","slice","ex","it","Promise","resolve","reject","testAsyncAux","then","valid","catch","pickFn","variant","rule","length","modifier","shift","nextFn","perform","performAsync","Modifier","ValidationError","Error","cause","target","remaining","super","captureStackTrace","Context","chain","nextRuleModifiers","ruleFn","push","apply","simple","async","every","_test","err","forEach","_check","executeAsyncRules","rules","_testAsync","v8n","undefined","Proxy","proxyContext","proxylessContext","customRules","context","obj","prop","newContext","_clone","availableModifiers","_applyModifier","_applyRule","availableRules","addRuleSet","ruleSet","targetContext","Object","keys","contextWithAvailableRules","contextWithAllRules","defineProperty","get","extend","newRules","assign","clearCustomRules","not","result","some","split","item","all","map","Boolean","strict","isSchemaRule","equal","expected","exact","number","allowInfinite","isFinite","integer","Number","isInteger","isIntegerPolyfill","numeric","isNaN","parseFloat","string","testType","boolean","null","array","object","instanceOf","instance","pattern","test","lowercase","uppercase","vowel","consonant","first","last","empty","min","max","minLength","maxLength","negative","positive","between","a","b","range","lessThan","n","lessThanOrEqual","greaterThan","greaterThanOrEqual","even","odd","includes","indexOf","schema","causes","key","nestedValidation","check","nested","testAsync","testSchema","passesAnyOf","validations","validation","optional","createOptionalRule","optionalAsync","asynchronous","considerTrimmedEmptyString","trim","Array","isArray","Math","floor"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v8n.esm.js b/dist/v8n.esm.js index e33b2e2..4ebcbad 100644 --- a/dist/v8n.esm.js +++ b/dist/v8n.esm.js @@ -9,13 +9,13 @@ Rule.prototype._test = function _test (value) { var fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = function () { return false; }; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex$1) { return false; } @@ -23,14 +23,14 @@ Rule.prototype._test = function _test (value) { Rule.prototype._check = function _check (value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), function (it) { return it; })(false)) { + if (testAux(this.modifiers.slice(), function (it) { return it; }, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } }; @@ -41,7 +41,8 @@ Rule.prototype._testAsync = function _testAsync (value) { return new Promise(function (resolve, reject) { testAsyncAux( this$1.modifiers.slice(), - this$1.fn + this$1.fn, + this$1 )(value) .then(function (valid) { if (valid) { @@ -60,21 +61,21 @@ function pickFn(fn, variant) { return typeof fn === 'object' ? fn[variant] : fn; } -function testAux(modifiers, fn) { +function testAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + var nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } -function testAsyncAux(modifiers, fn) { +function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + var nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return function (value) { return Promise.resolve(pickFn(fn, 'async')(value)); }; } @@ -302,8 +303,40 @@ var availableModifiers = { simple: function (fn) { return function (value) { return value !== false && split(value).every(fn); }; }, async: function (fn) { return function (value) { return Promise.all(split(value).map(fn)).then(function (result) { return result.every(Boolean); }); }; }, }, + + strict: { + simple: function (fn, rule) { return function (value) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }; }, + async: function (fn, rule) { return function (value) { return Promise.resolve(fn(value)) + .then(function (result) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(function () { return false; }); }; }, + }, }; +function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); +} + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/dist/v8n.min.js b/dist/v8n.min.js index b3727ed..224bf79 100644 --- a/dist/v8n.min.js +++ b/dist/v8n.min.js @@ -1,2 +1,2 @@ -!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(n="undefined"!=typeof globalThis?globalThis:n||self).v8n=t()}(this,(function(){"use strict";var n=function(n,t,r,e){this.name=n,this.fn=t,this.args=r,this.modifiers=e};function t(n,t){return void 0===t&&(t="simple"),"object"==typeof n?n[t]:n}function r(n,e){if(n.length){var u=n.shift(),i=r(n,e);return u.perform(i)}return t(e)}function e(n,r){if(n.length){var u=n.shift(),i=e(n,r);return u.performAsync(i)}return function(n){return Promise.resolve(t(r,"async")(n))}}n.prototype._test=function(n){var t=this.fn;try{r(this.modifiers.slice(),t)(n)}catch(n){t=function(){return!1}}try{return r(this.modifiers.slice(),t)(n)}catch(n){return!1}},n.prototype._check=function(n){try{r(this.modifiers.slice(),this.fn)(n)}catch(n){if(r(this.modifiers.slice(),(function(n){return n}))(!1))return}if(!r(this.modifiers.slice(),this.fn)(n))throw null},n.prototype._testAsync=function(n){var t=this;return new Promise((function(r,u){e(t.modifiers.slice(),t.fn)(n).then((function(t){t?r(n):u(null)})).catch((function(n){return u(n)}))}))};var u=function(n,t,r){this.name=n,this.perform=t,this.performAsync=r},i=function(n){function t(r,e,u,i){for(var o=[],c=arguments.length-4;c-- >0;)o[c]=arguments[c+4];n.call(this,o),n.captureStackTrace&&n.captureStackTrace(this,t),this.rule=r,this.value=e,this.cause=u,this.target=i}return n&&(t.__proto__=n),t.prototype=Object.create(n&&n.prototype),t.prototype.constructor=t,t}(Error),o=function(n,t){void 0===n&&(n=[]),void 0===t&&(t=[]),this.chain=n,this.nextRuleModifiers=t};function c(n,t,r,e){if(t.length){var u=t.shift();u._testAsync(n).then((function(){c(n,t,r,e)}),(function(t){e(new i(u,n,t))}))}else r(n)}function f(){return void 0!==typeof Proxy?a(new o):l(new o)}o.prototype._applyRule=function(t,r){var e=this;return function(){for(var u=[],i=arguments.length;i--;)u[i]=arguments[i];return e.chain.push(new n(r,t.apply(e,u),u,e.nextRuleModifiers)),e.nextRuleModifiers=[],e}},o.prototype._applyModifier=function(n,t){return this.nextRuleModifiers.push(new u(t,n.simple,n.async)),this},o.prototype._clone=function(){return new o(this.chain.slice(),this.nextRuleModifiers.slice())},o.prototype.test=function(n){return this.chain.every((function(t){return t._test(n)}))},o.prototype.testAll=function(n){var t=[];return this.chain.forEach((function(r){try{r._check(n)}catch(e){t.push(new i(r,n,e))}})),t},o.prototype.check=function(n){this.chain.forEach((function(t){try{t._check(n)}catch(r){throw new i(t,n,r)}}))},o.prototype.testAsync=function(n){var t=this;return new Promise((function(r,e){c(n,t.chain.slice(),r,e)}))};var s={};function a(n){return new Proxy(n,{get:function(t,r){if(r in t)return t[r];var e=a(n._clone());return r in h?e._applyModifier(h[r],r):r in s?e._applyRule(s[r],r):r in y?e._applyRule(y[r],r):void 0}})}function l(n){var t=function(n,t){return Object.keys(n).forEach((function(r){t[r]=function(){for(var e=[],u=arguments.length;u--;)e[u]=arguments[u];var i=l(t._clone()),o=i._applyRule(n[r],r).apply(void 0,e);return o}})),t},r=t(y,n),e=t(s,r);return Object.keys(h).forEach((function(n){Object.defineProperty(e,n,{get:function(){return l(e._clone())._applyModifier(h[n],n)}})})),e}f.extend=function(n){Object.assign(s,n)},f.clearCustomRules=function(){s={}};var h={not:{simple:function(n){return function(t){return!n(t)}},async:function(n){return function(t){return Promise.resolve(n(t)).then((function(n){return!n})).catch((function(){return!0}))}}},some:{simple:function(n){return function(t){return p(t).some((function(t){try{return n(t)}catch(n){return!1}}))}},async:function(n){return function(t){return Promise.all(p(t).map((function(t){try{return n(t).catch((function(){return!1}))}catch(n){return!1}}))).then((function(n){return n.some(Boolean)}))}}},every:{simple:function(n){return function(t){return!1!==t&&p(t).every(n)}},async:function(n){return function(t){return Promise.all(p(t).map(n)).then((function(n){return n.every(Boolean)}))}}}};function p(n){return"string"==typeof n?n.split(""):n}var y={equal:function(n){return function(t){return t==n}},exact:function(n){return function(t){return t===n}},number:function(n){return void 0===n&&(n=!0),function(t){return"number"==typeof t&&(n||isFinite(t))}},integer:function(){return function(n){return(Number.isInteger||v)(n)}},numeric:function(){return function(n){return!isNaN(parseFloat(n))&&isFinite(n)}},string:function(){return d("string")},boolean:function(){return d("boolean")},undefined:function(){return d("undefined")},null:function(){return d("null")},array:function(){return d("array")},object:function(){return d("object")},instanceOf:function(n){return function(t){return t instanceof n}},pattern:function(n){return function(t){return n.test(t)}},lowercase:function(){return function(n){return/^([a-z]+\s*)+$/.test(n)}},uppercase:function(){return function(n){return/^([A-Z]+\s*)+$/.test(n)}},vowel:function(){return function(n){return/^[aeiou]+$/i.test(n)}},consonant:function(){return function(n){return/^(?=[^aeiou])([a-z]+)$/i.test(n)}},first:function(n){return function(t){return t[0]==n}},last:function(n){return function(t){return t[t.length-1]==n}},empty:function(){return function(n){return 0===n.length}},length:function(n,t){return function(r){return r.length>=n&&r.length<=(t||n)}},minLength:function(n){return function(t){return t.length>=n}},maxLength:function(n){return function(t){return t.length<=n}},negative:function(){return function(n){return n<0}},positive:function(){return function(n){return n>=0}},between:function(n,t){return function(r){return r>=n&&r<=t}},range:function(n,t){return function(r){return r>=n&&r<=t}},lessThan:function(n){return function(t){return tn}},greaterThanOrEqual:function(n){return function(t){return t>=n}},even:function(){return function(n){return n%2==0}},odd:function(){return function(n){return n%2!=0}},includes:function(n){return function(t){return~t.indexOf(n)}},schema:function(n){return function(n){return{simple:function(t){var r=[];if(Object.keys(n).forEach((function(e){var u=n[e];try{u.check((t||{})[e])}catch(n){n.target=e,r.push(n)}})),r.length>0)throw r;return!0},async:function(t){var r=[],e=Object.keys(n).map((function(e){return n[e].testAsync((t||{})[e]).catch((function(n){n.target=e,r.push(n)}))}));return Promise.all(e).then((function(){if(r.length>0)throw r;return!0}))}}}(n)},passesAnyOf:function(){for(var n=[],t=arguments.length;t--;)n[t]=arguments[t];return function(t){return n.some((function(n){return n.test(t)}))}},optional:m(!1),optionalAsync:m(!0)};function m(n){return function(t,r){return void 0===r&&(r=!1),function(e){if(r&&"string"==typeof e&&""===e.trim())return!0;if(null!=e){if(n)return t.testAsync(e);t.check(e)}return!0}}}function d(n){return function(t){return Array.isArray(t)&&"array"===n||null===t&&"null"===n||typeof t===n}}function v(n){return"number"==typeof n&&isFinite(n)&&Math.floor(n)===n}return f})); +!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(n="undefined"!=typeof globalThis?globalThis:n||self).v8n=t()}(this,(function(){"use strict";var n=function(n,t,r,e){this.name=n,this.fn=t,this.args=r,this.modifiers=e};function t(n,t){return void 0===t&&(t="simple"),"object"==typeof n?n[t]:n}function r(n,e,u){if(n.length){var i=n.shift(),o=r(n,e,u);return i.perform(o,u)}return t(e)}function e(n,r,u){if(n.length){var i=n.shift(),o=e(n,r,u);return i.performAsync(o,u)}return function(n){return Promise.resolve(t(r,"async")(n))}}n.prototype._test=function(n){var t=this.fn;try{r(this.modifiers.slice(),t,this)(n)}catch(n){t=function(){return!1}}try{return r(this.modifiers.slice(),t,this)(n)}catch(n){return!1}},n.prototype._check=function(n){try{r(this.modifiers.slice(),this.fn,this)(n)}catch(n){if(r(this.modifiers.slice(),(function(n){return n}),this)(!1))return}if(!r(this.modifiers.slice(),this.fn,this)(n))throw null},n.prototype._testAsync=function(n){var t=this;return new Promise((function(r,u){e(t.modifiers.slice(),t.fn,t)(n).then((function(t){t?r(n):u(null)})).catch((function(n){return u(n)}))}))};var u=function(n,t,r){this.name=n,this.perform=t,this.performAsync=r},i=function(n){function t(r,e,u,i){for(var o=[],c=arguments.length-4;c-- >0;)o[c]=arguments[c+4];n.call(this,o),n.captureStackTrace&&n.captureStackTrace(this,t),this.rule=r,this.value=e,this.cause=u,this.target=i}return n&&(t.__proto__=n),t.prototype=Object.create(n&&n.prototype),t.prototype.constructor=t,t}(Error),o=function(n,t){void 0===n&&(n=[]),void 0===t&&(t=[]),this.chain=n,this.nextRuleModifiers=t};function c(n,t,r,e){if(t.length){var u=t.shift();u._testAsync(n).then((function(){c(n,t,r,e)}),(function(t){e(new i(u,n,t))}))}else r(n)}function f(){return void 0!==typeof Proxy?a(new o):h(new o)}o.prototype._applyRule=function(t,r){var e=this;return function(){for(var u=[],i=arguments.length;i--;)u[i]=arguments[i];return e.chain.push(new n(r,t.apply(e,u),u,e.nextRuleModifiers)),e.nextRuleModifiers=[],e}},o.prototype._applyModifier=function(n,t){return this.nextRuleModifiers.push(new u(t,n.simple,n.async)),this},o.prototype._clone=function(){return new o(this.chain.slice(),this.nextRuleModifiers.slice())},o.prototype.test=function(n){return this.chain.every((function(t){return t._test(n)}))},o.prototype.testAll=function(n){var t=[];return this.chain.forEach((function(r){try{r._check(n)}catch(e){t.push(new i(r,n,e))}})),t},o.prototype.check=function(n){this.chain.forEach((function(t){try{t._check(n)}catch(r){throw new i(t,n,r)}}))},o.prototype.testAsync=function(n){var t=this;return new Promise((function(r,e){c(n,t.chain.slice(),r,e)}))};var s={};function a(n){return new Proxy(n,{get:function(t,r){if(r in t)return t[r];var e=a(n._clone());return r in l?e._applyModifier(l[r],r):r in s?e._applyRule(s[r],r):r in m?e._applyRule(m[r],r):void 0}})}function h(n){var t=function(n,t){return Object.keys(n).forEach((function(r){t[r]=function(){for(var e=[],u=arguments.length;u--;)e[u]=arguments[u];var i=h(t._clone()),o=i._applyRule(n[r],r).apply(void 0,e);return o}})),t},r=t(m,n),e=t(s,r);return Object.keys(l).forEach((function(n){Object.defineProperty(e,n,{get:function(){return h(e._clone())._applyModifier(l[n],n)}})})),e}f.extend=function(n){Object.assign(s,n)},f.clearCustomRules=function(){s={}};var l={not:{simple:function(n){return function(t){return!n(t)}},async:function(n){return function(t){return Promise.resolve(n(t)).then((function(n){return!n})).catch((function(){return!0}))}}},some:{simple:function(n){return function(t){return y(t).some((function(t){try{return n(t)}catch(n){return!1}}))}},async:function(n){return function(t){return Promise.all(y(t).map((function(t){try{return n(t).catch((function(){return!1}))}catch(n){return!1}}))).then((function(n){return n.some(Boolean)}))}}},every:{simple:function(n){return function(t){return!1!==t&&y(t).every(n)}},async:function(n){return function(t){return Promise.all(y(t).map(n)).then((function(n){return n.every(Boolean)}))}}},strict:{simple:function(n,t){return function(r){return p(t)&&r&&"object"==typeof r?Object.keys(t.args[0]).length===Object.keys(r).length&&n(r):n(r)}},async:function(n,t){return function(r){return Promise.resolve(n(r)).then((function(n){return p(t)&&r&&"object"==typeof r?Object.keys(t.args[0]).length===Object.keys(r).length&&n:n})).catch((function(){return!1}))}}}};function p(n){return n&&"schema"===n.name&&n.args.length>0&&"object"==typeof n.args[0]}function y(n){return"string"==typeof n?n.split(""):n}var m={equal:function(n){return function(t){return t==n}},exact:function(n){return function(t){return t===n}},number:function(n){return void 0===n&&(n=!0),function(t){return"number"==typeof t&&(n||isFinite(t))}},integer:function(){return function(n){return(Number.isInteger||d)(n)}},numeric:function(){return function(n){return!isNaN(parseFloat(n))&&isFinite(n)}},string:function(){return v("string")},boolean:function(){return v("boolean")},undefined:function(){return v("undefined")},null:function(){return v("null")},array:function(){return v("array")},object:function(){return v("object")},instanceOf:function(n){return function(t){return t instanceof n}},pattern:function(n){return function(t){return n.test(t)}},lowercase:function(){return function(n){return/^([a-z]+\s*)+$/.test(n)}},uppercase:function(){return function(n){return/^([A-Z]+\s*)+$/.test(n)}},vowel:function(){return function(n){return/^[aeiou]+$/i.test(n)}},consonant:function(){return function(n){return/^(?=[^aeiou])([a-z]+)$/i.test(n)}},first:function(n){return function(t){return t[0]==n}},last:function(n){return function(t){return t[t.length-1]==n}},empty:function(){return function(n){return 0===n.length}},length:function(n,t){return function(r){return r.length>=n&&r.length<=(t||n)}},minLength:function(n){return function(t){return t.length>=n}},maxLength:function(n){return function(t){return t.length<=n}},negative:function(){return function(n){return n<0}},positive:function(){return function(n){return n>=0}},between:function(n,t){return function(r){return r>=n&&r<=t}},range:function(n,t){return function(r){return r>=n&&r<=t}},lessThan:function(n){return function(t){return tn}},greaterThanOrEqual:function(n){return function(t){return t>=n}},even:function(){return function(n){return n%2==0}},odd:function(){return function(n){return n%2!=0}},includes:function(n){return function(t){return~t.indexOf(n)}},schema:function(n){return function(n){return{simple:function(t){var r=[];if(Object.keys(n).forEach((function(e){var u=n[e];try{u.check((t||{})[e])}catch(n){n.target=e,r.push(n)}})),r.length>0)throw r;return!0},async:function(t){var r=[],e=Object.keys(n).map((function(e){return n[e].testAsync((t||{})[e]).catch((function(n){n.target=e,r.push(n)}))}));return Promise.all(e).then((function(){if(r.length>0)throw r;return!0}))}}}(n)},passesAnyOf:function(){for(var n=[],t=arguments.length;t--;)n[t]=arguments[t];return function(t){return n.some((function(n){return n.test(t)}))}},optional:g(!1),optionalAsync:g(!0)};function g(n){return function(t,r){return void 0===r&&(r=!1),function(e){if(r&&"string"==typeof e&&""===e.trim())return!0;if(null!=e){if(n)return t.testAsync(e);t.check(e)}return!0}}}function v(n){return function(t){return Array.isArray(t)&&"array"===n||null===t&&"null"===n||typeof t===n}}function d(n){return"number"==typeof n&&isFinite(n)&&Math.floor(n)===n}return f})); //# sourceMappingURL=v8n.min.js.map diff --git a/dist/v8n.min.js.map b/dist/v8n.min.js.map index 91b7b9b..10989d9 100644 --- a/dist/v8n.min.js.map +++ b/dist/v8n.min.js.map @@ -1 +1 @@ -{"version":3,"file":"v8n.min.js","sources":["../src/Rule.js","../src/Modifier.js","../src/ValidationError.js","../src/Context.js","../src/v8n.js"],"sourcesContent":["class Rule {\r\n constructor(name, fn, args, modifiers) {\r\n this.name = name;\r\n this.fn = fn;\r\n this.args = args;\r\n this.modifiers = modifiers;\r\n }\r\n\r\n _test(value) {\r\n let fn = this.fn;\r\n\r\n try {\r\n testAux(this.modifiers.slice(), fn)(value);\r\n } catch (ex) {\r\n fn = () => false;\r\n }\r\n\r\n try {\r\n return testAux(this.modifiers.slice(), fn)(value);\r\n } catch (ex) {\r\n return false;\r\n }\r\n }\r\n\r\n _check(value) {\r\n try {\r\n testAux(this.modifiers.slice(), this.fn)(value);\r\n } catch (ex) {\r\n if (testAux(this.modifiers.slice(), it => it)(false)) {\r\n return;\r\n }\r\n }\r\n\r\n if (!testAux(this.modifiers.slice(), this.fn)(value)) {\r\n throw null;\r\n }\r\n }\r\n\r\n _testAsync(value) {\r\n return new Promise((resolve, reject) => {\r\n testAsyncAux(\r\n this.modifiers.slice(),\r\n this.fn,\r\n )(value)\r\n .then(valid => {\r\n if (valid) {\r\n resolve(value);\r\n } else {\r\n reject(null);\r\n }\r\n })\r\n .catch(ex => reject(ex));\r\n });\r\n }\r\n}\r\n\r\nfunction pickFn(fn, variant = 'simple') {\r\n return typeof fn === 'object' ? fn[variant] : fn;\r\n}\r\n\r\nfunction testAux(modifiers, fn) {\r\n if (modifiers.length) {\r\n const modifier = modifiers.shift();\r\n const nextFn = testAux(modifiers, fn);\r\n return modifier.perform(nextFn);\r\n } else {\r\n return pickFn(fn);\r\n }\r\n}\r\n\r\nfunction testAsyncAux(modifiers, fn) {\r\n if (modifiers.length) {\r\n const modifier = modifiers.shift();\r\n const nextFn = testAsyncAux(modifiers, fn);\r\n return modifier.performAsync(nextFn);\r\n } else {\r\n return value => Promise.resolve(pickFn(fn, 'async')(value));\r\n }\r\n}\r\n\r\nexport default Rule;\r\n","class Modifier {\r\n constructor(name, perform, performAsync) {\r\n this.name = name;\r\n this.perform = perform;\r\n this.performAsync = performAsync;\r\n }\r\n}\r\n\r\nexport default Modifier;\r\n","class ValidationError extends Error {\r\n constructor(rule, value, cause, target, ...remaining) {\r\n super(remaining);\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, ValidationError);\r\n }\r\n this.rule = rule;\r\n this.value = value;\r\n this.cause = cause;\r\n this.target = target;\r\n }\r\n}\r\n\r\nexport default ValidationError;\r\n","import Rule from './Rule';\r\nimport Modifier from './Modifier';\r\nimport ValidationError from './ValidationError';\r\n\r\nclass Context {\r\n constructor(chain = [], nextRuleModifiers = []) {\r\n this.chain = chain;\r\n this.nextRuleModifiers = nextRuleModifiers;\r\n }\r\n\r\n _applyRule(ruleFn, name) {\r\n return (...args) => {\r\n this.chain.push(\r\n new Rule(name, ruleFn.apply(this, args), args, this.nextRuleModifiers),\r\n );\r\n this.nextRuleModifiers = [];\r\n return this;\r\n };\r\n }\r\n\r\n _applyModifier(modifier, name) {\r\n this.nextRuleModifiers.push(\r\n new Modifier(name, modifier.simple, modifier.async),\r\n );\r\n return this;\r\n }\r\n\r\n _clone() {\r\n return new Context(this.chain.slice(), this.nextRuleModifiers.slice());\r\n }\r\n\r\n test(value) {\r\n return this.chain.every(rule => rule._test(value));\r\n }\r\n\r\n testAll(value) {\r\n const err = [];\r\n this.chain.forEach(rule => {\r\n try {\r\n rule._check(value);\r\n } catch (ex) {\r\n err.push(new ValidationError(rule, value, ex));\r\n }\r\n });\r\n return err;\r\n }\r\n\r\n check(value) {\r\n this.chain.forEach(rule => {\r\n try {\r\n rule._check(value);\r\n } catch (ex) {\r\n throw new ValidationError(rule, value, ex);\r\n }\r\n });\r\n }\r\n\r\n testAsync(value) {\r\n return new Promise((resolve, reject) => {\r\n executeAsyncRules(value, this.chain.slice(), resolve, reject);\r\n });\r\n }\r\n}\r\n\r\nfunction executeAsyncRules(value, rules, resolve, reject) {\r\n if (rules.length) {\r\n const rule = rules.shift();\r\n rule._testAsync(value).then(\r\n () => {\r\n executeAsyncRules(value, rules, resolve, reject);\r\n },\r\n cause => {\r\n reject(new ValidationError(rule, value, cause));\r\n },\r\n );\r\n } else {\r\n resolve(value);\r\n }\r\n}\r\n\r\nexport default Context;\r\n","import Context from './Context';\r\n\r\nfunction v8n() {\r\n return typeof Proxy !== undefined\r\n ? proxyContext(new Context())\r\n : proxylessContext(new Context());\r\n}\r\n\r\n// Custom rules\r\nlet customRules = {};\r\n\r\nv8n.extend = function(newRules) {\r\n Object.assign(customRules, newRules);\r\n};\r\n\r\nv8n.clearCustomRules = function() {\r\n customRules = {};\r\n};\r\n\r\nfunction proxyContext(context) {\r\n return new Proxy(context, {\r\n get(obj, prop) {\r\n if (prop in obj) {\r\n return obj[prop];\r\n }\r\n\r\n const newContext = proxyContext(context._clone());\r\n\r\n if (prop in availableModifiers) {\r\n return newContext._applyModifier(availableModifiers[prop], prop);\r\n }\r\n if (prop in customRules) {\r\n return newContext._applyRule(customRules[prop], prop);\r\n }\r\n if (prop in availableRules) {\r\n return newContext._applyRule(availableRules[prop], prop);\r\n }\r\n },\r\n });\r\n}\r\n\r\nfunction proxylessContext(context) {\r\n const addRuleSet = (ruleSet, targetContext) => {\r\n Object.keys(ruleSet).forEach(prop => {\r\n targetContext[prop] = (...args) => {\r\n const newContext = proxylessContext(targetContext._clone());\r\n const contextWithRuleApplied = newContext._applyRule(\r\n ruleSet[prop],\r\n prop,\r\n )(...args);\r\n return contextWithRuleApplied;\r\n };\r\n });\r\n return targetContext;\r\n };\r\n\r\n const contextWithAvailableRules = addRuleSet(availableRules, context);\r\n const contextWithAllRules = addRuleSet(\r\n customRules,\r\n contextWithAvailableRules,\r\n );\r\n\r\n Object.keys(availableModifiers).forEach(prop => {\r\n Object.defineProperty(contextWithAllRules, prop, {\r\n get: () => {\r\n const newContext = proxylessContext(contextWithAllRules._clone());\r\n return newContext._applyModifier(availableModifiers[prop], prop);\r\n },\r\n });\r\n });\r\n\r\n return contextWithAllRules;\r\n}\r\n\r\nconst availableModifiers = {\r\n not: {\r\n simple: fn => value => !fn(value),\r\n async: fn => value =>\r\n Promise.resolve(fn(value))\r\n .then(result => !result)\r\n .catch(() => true),\r\n },\r\n\r\n some: {\r\n simple: fn => value => {\r\n return split(value).some(item => {\r\n try {\r\n return fn(item);\r\n } catch (ex) {\r\n return false;\r\n }\r\n });\r\n },\r\n async: fn => value => {\r\n return Promise.all(\r\n split(value).map(item => {\r\n try {\r\n return fn(item).catch(() => false);\r\n } catch (ex) {\r\n return false;\r\n }\r\n }),\r\n ).then(result => result.some(Boolean));\r\n },\r\n },\r\n\r\n every: {\r\n simple: fn => value => value !== false && split(value).every(fn),\r\n async: fn => value =>\r\n Promise.all(split(value).map(fn)).then(result => result.every(Boolean)),\r\n },\r\n};\r\n\r\nfunction split(value) {\r\n if (typeof value === 'string') {\r\n return value.split('');\r\n }\r\n return value;\r\n}\r\n\r\nconst availableRules = {\r\n // Value\r\n\r\n equal: expected => value => value == expected,\r\n\r\n exact: expected => value => value === expected,\r\n\r\n // Types\r\n\r\n number: (allowInfinite = true) => value =>\r\n typeof value === 'number' && (allowInfinite || isFinite(value)),\r\n\r\n integer: () => value => {\r\n const isInteger = Number.isInteger || isIntegerPolyfill;\r\n return isInteger(value);\r\n },\r\n\r\n numeric: () => value => !isNaN(parseFloat(value)) && isFinite(value),\r\n\r\n string: () => testType('string'),\r\n\r\n boolean: () => testType('boolean'),\r\n\r\n undefined: () => testType('undefined'),\r\n\r\n null: () => testType('null'),\r\n\r\n array: () => testType('array'),\r\n\r\n object: () => testType('object'),\r\n\r\n instanceOf: instance => value => value instanceof instance,\r\n\r\n // Pattern\r\n\r\n pattern: expected => value => expected.test(value),\r\n\r\n lowercase: () => value => /^([a-z]+\\s*)+$/.test(value),\r\n\r\n uppercase: () => value => /^([A-Z]+\\s*)+$/.test(value),\r\n\r\n vowel: () => value => /^[aeiou]+$/i.test(value),\r\n\r\n consonant: () => value => /^(?=[^aeiou])([a-z]+)$/i.test(value),\r\n\r\n // Value at\r\n\r\n first: expected => value => value[0] == expected,\r\n\r\n last: expected => value => value[value.length - 1] == expected,\r\n\r\n // Length\r\n\r\n empty: () => value => value.length === 0,\r\n\r\n length: (min, max) => value =>\r\n value.length >= min && value.length <= (max || min),\r\n\r\n minLength: min => value => value.length >= min,\r\n\r\n maxLength: max => value => value.length <= max,\r\n\r\n // Range\r\n\r\n negative: () => value => value < 0,\r\n\r\n positive: () => value => value >= 0,\r\n\r\n between: (a, b) => value => value >= a && value <= b,\r\n\r\n range: (a, b) => value => value >= a && value <= b,\r\n\r\n lessThan: n => value => value < n,\r\n\r\n lessThanOrEqual: n => value => value <= n,\r\n\r\n greaterThan: n => value => value > n,\r\n\r\n greaterThanOrEqual: n => value => value >= n,\r\n\r\n // Divisible\r\n\r\n even: () => value => value % 2 === 0,\r\n\r\n odd: () => value => value % 2 !== 0,\r\n\r\n includes: expected => value => ~value.indexOf(expected),\r\n\r\n schema: schema => testSchema(schema),\r\n\r\n // branching\r\n\r\n passesAnyOf: (...validations) => value =>\r\n validations.some(validation => validation.test(value)),\r\n\r\n optional: createOptionalRule(false),\r\n optionalAsync: createOptionalRule(true),\r\n};\r\n\r\nfunction createOptionalRule(asynchronous) {\r\n return (validation, considerTrimmedEmptyString = false) => value => {\r\n if (\r\n considerTrimmedEmptyString &&\r\n typeof value === 'string' &&\r\n value.trim() === ''\r\n ) {\r\n return true;\r\n }\r\n\r\n if (value !== undefined && value !== null) {\r\n if (!asynchronous) {\r\n validation.check(value);\r\n } else {\r\n return validation.testAsync(value);\r\n }\r\n }\r\n return true;\r\n };\r\n}\r\n\r\nfunction testType(expected) {\r\n return value => {\r\n return (\r\n (Array.isArray(value) && expected === 'array') ||\r\n (value === null && expected === 'null') ||\r\n typeof value === expected\r\n );\r\n };\r\n}\r\n\r\nfunction isIntegerPolyfill(value) {\r\n return (\r\n typeof value === 'number' && isFinite(value) && Math.floor(value) === value\r\n );\r\n}\r\n\r\nfunction testSchema(schema) {\r\n return {\r\n simple: value => {\r\n const causes = [];\r\n Object.keys(schema).forEach(key => {\r\n const nestedValidation = schema[key];\r\n try {\r\n nestedValidation.check((value || {})[key]);\r\n } catch (ex) {\r\n ex.target = key;\r\n causes.push(ex);\r\n }\r\n });\r\n if (causes.length > 0) {\r\n throw causes;\r\n }\r\n return true;\r\n },\r\n async: value => {\r\n const causes = [];\r\n const nested = Object.keys(schema).map(key => {\r\n const nestedValidation = schema[key];\r\n return nestedValidation.testAsync((value || {})[key]).catch(ex => {\r\n ex.target = key;\r\n causes.push(ex);\r\n });\r\n });\r\n return Promise.all(nested).then(() => {\r\n if (causes.length > 0) {\r\n throw causes;\r\n }\r\n\r\n return true;\r\n });\r\n },\r\n };\r\n}\r\n\r\nexport default v8n;\r\n"],"names":["Rule","name","fn","args","modifiers","this","pickFn","variant","testAux","length","const","modifier","shift","nextFn","perform","testAsyncAux","performAsync","value","Promise","resolve","_test","let","slice","ex","_check","it","_testAsync","reject","then","valid","catch","Modifier","ValidationError","rule","cause","target","super","remaining","Error","captureStackTrace","Context","chain","nextRuleModifiers","executeAsyncRules","rules","v8n","undefined","Proxy","proxyContext","proxylessContext","_applyRule","ruleFn","push","apply","_applyModifier","simple","async","_clone","test","every","testAll","err","forEach","check","testAsync","customRules","context","get","obj","prop","newContext","availableModifiers","availableRules","addRuleSet","ruleSet","targetContext","Object","keys","contextWithRuleApplied","contextWithAvailableRules","contextWithAllRules","defineProperty","extend","newRules","assign","clearCustomRules","not","result","some","split","item","all","map","Boolean","equal","expected","exact","number","allowInfinite","isFinite","integer","Number","isInteger","isIntegerPolyfill","numeric","isNaN","parseFloat","string","testType","boolean","null","array","object","instanceOf","instance","pattern","lowercase","uppercase","vowel","consonant","first","last","empty","min","max","minLength","maxLength","negative","positive","between","a","b","range","lessThan","n","lessThanOrEqual","greaterThan","greaterThanOrEqual","even","odd","includes","indexOf","schema","causes","key","nestedValidation","nested","testSchema","passesAnyOf","validations","validation","optional","createOptionalRule","optionalAsync","asynchronous","considerTrimmedEmptyString","trim","Array","isArray","Math","floor"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"v8n.min.js","sources":["../src/Rule.js","../src/Modifier.js","../src/ValidationError.js","../src/Context.js","../src/v8n.js"],"sourcesContent":["class Rule {\n constructor(name, fn, args, modifiers) {\n this.name = name;\n this.fn = fn;\n this.args = args;\n this.modifiers = modifiers;\n }\n\n _test(value) {\n let fn = this.fn;\n\n try {\n testAux(this.modifiers.slice(), fn, this)(value);\n } catch (ex) {\n fn = () => false;\n }\n\n try {\n return testAux(this.modifiers.slice(), fn, this)(value);\n } catch (ex) {\n return false;\n }\n }\n\n _check(value) {\n try {\n testAux(this.modifiers.slice(), this.fn, this)(value);\n } catch (ex) {\n if (testAux(this.modifiers.slice(), it => it, this)(false)) {\n return;\n }\n }\n\n if (!testAux(this.modifiers.slice(), this.fn, this)(value)) {\n throw null;\n }\n }\n\n _testAsync(value) {\n return new Promise((resolve, reject) => {\n testAsyncAux(\n this.modifiers.slice(),\n this.fn,\n this,\n )(value)\n .then(valid => {\n if (valid) {\n resolve(value);\n } else {\n reject(null);\n }\n })\n .catch(ex => reject(ex));\n });\n }\n}\n\nfunction pickFn(fn, variant = 'simple') {\n return typeof fn === 'object' ? fn[variant] : fn;\n}\n\nfunction testAux(modifiers, fn, rule) {\n if (modifiers.length) {\n const modifier = modifiers.shift();\n const nextFn = testAux(modifiers, fn, rule);\n return modifier.perform(nextFn, rule);\n } else {\n return pickFn(fn);\n }\n}\n\nfunction testAsyncAux(modifiers, fn, rule) {\n if (modifiers.length) {\n const modifier = modifiers.shift();\n const nextFn = testAsyncAux(modifiers, fn, rule);\n return modifier.performAsync(nextFn, rule);\n } else {\n return value => Promise.resolve(pickFn(fn, 'async')(value));\n }\n}\n\nexport default Rule;\n","class Modifier {\n constructor(name, perform, performAsync) {\n this.name = name;\n this.perform = perform;\n this.performAsync = performAsync;\n }\n}\n\nexport default Modifier;\n","class ValidationError extends Error {\n constructor(rule, value, cause, target, ...remaining) {\n super(remaining);\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n this.rule = rule;\n this.value = value;\n this.cause = cause;\n this.target = target;\n }\n}\n\nexport default ValidationError;\n","import Rule from './Rule';\nimport Modifier from './Modifier';\nimport ValidationError from './ValidationError';\n\nclass Context {\n constructor(chain = [], nextRuleModifiers = []) {\n this.chain = chain;\n this.nextRuleModifiers = nextRuleModifiers;\n }\n\n _applyRule(ruleFn, name) {\n return (...args) => {\n this.chain.push(\n new Rule(name, ruleFn.apply(this, args), args, this.nextRuleModifiers),\n );\n this.nextRuleModifiers = [];\n return this;\n };\n }\n\n _applyModifier(modifier, name) {\n this.nextRuleModifiers.push(\n new Modifier(name, modifier.simple, modifier.async),\n );\n return this;\n }\n\n _clone() {\n return new Context(this.chain.slice(), this.nextRuleModifiers.slice());\n }\n\n test(value) {\n return this.chain.every(rule => rule._test(value));\n }\n\n testAll(value) {\n const err = [];\n this.chain.forEach(rule => {\n try {\n rule._check(value);\n } catch (ex) {\n err.push(new ValidationError(rule, value, ex));\n }\n });\n return err;\n }\n\n check(value) {\n this.chain.forEach(rule => {\n try {\n rule._check(value);\n } catch (ex) {\n throw new ValidationError(rule, value, ex);\n }\n });\n }\n\n testAsync(value) {\n return new Promise((resolve, reject) => {\n executeAsyncRules(value, this.chain.slice(), resolve, reject);\n });\n }\n}\n\nfunction executeAsyncRules(value, rules, resolve, reject) {\n if (rules.length) {\n const rule = rules.shift();\n rule._testAsync(value).then(\n () => {\n executeAsyncRules(value, rules, resolve, reject);\n },\n cause => {\n reject(new ValidationError(rule, value, cause));\n },\n );\n } else {\n resolve(value);\n }\n}\n\nexport default Context;\n","import Context from './Context';\n\nfunction v8n() {\n return typeof Proxy !== undefined\n ? proxyContext(new Context())\n : proxylessContext(new Context());\n}\n\n// Custom rules\nlet customRules = {};\n\nv8n.extend = function(newRules) {\n Object.assign(customRules, newRules);\n};\n\nv8n.clearCustomRules = function() {\n customRules = {};\n};\n\nfunction proxyContext(context) {\n return new Proxy(context, {\n get(obj, prop) {\n if (prop in obj) {\n return obj[prop];\n }\n\n const newContext = proxyContext(context._clone());\n\n if (prop in availableModifiers) {\n return newContext._applyModifier(availableModifiers[prop], prop);\n }\n if (prop in customRules) {\n return newContext._applyRule(customRules[prop], prop);\n }\n if (prop in availableRules) {\n return newContext._applyRule(availableRules[prop], prop);\n }\n },\n });\n}\n\nfunction proxylessContext(context) {\n const addRuleSet = (ruleSet, targetContext) => {\n Object.keys(ruleSet).forEach(prop => {\n targetContext[prop] = (...args) => {\n const newContext = proxylessContext(targetContext._clone());\n const contextWithRuleApplied = newContext._applyRule(\n ruleSet[prop],\n prop,\n )(...args);\n return contextWithRuleApplied;\n };\n });\n return targetContext;\n };\n\n const contextWithAvailableRules = addRuleSet(availableRules, context);\n const contextWithAllRules = addRuleSet(\n customRules,\n contextWithAvailableRules,\n );\n\n Object.keys(availableModifiers).forEach(prop => {\n Object.defineProperty(contextWithAllRules, prop, {\n get: () => {\n const newContext = proxylessContext(contextWithAllRules._clone());\n return newContext._applyModifier(availableModifiers[prop], prop);\n },\n });\n });\n\n return contextWithAllRules;\n}\n\nconst availableModifiers = {\n not: {\n simple: fn => value => !fn(value),\n async: fn => value =>\n Promise.resolve(fn(value))\n .then(result => !result)\n .catch(() => true),\n },\n\n some: {\n simple: fn => value => {\n return split(value).some(item => {\n try {\n return fn(item);\n } catch (ex) {\n return false;\n }\n });\n },\n async: fn => value => {\n return Promise.all(\n split(value).map(item => {\n try {\n return fn(item).catch(() => false);\n } catch (ex) {\n return false;\n }\n }),\n ).then(result => result.some(Boolean));\n },\n },\n\n every: {\n simple: fn => value => value !== false && split(value).every(fn),\n async: fn => value =>\n Promise.all(split(value).map(fn)).then(result => result.every(Boolean)),\n },\n\n strict: {\n simple: (fn, rule) => value => {\n if (isSchemaRule(rule) && value && typeof value === 'object') {\n return (\n Object.keys(rule.args[0]).length === Object.keys(value).length &&\n fn(value)\n );\n }\n return fn(value);\n },\n async: (fn, rule) => value =>\n Promise.resolve(fn(value))\n .then(result => {\n if (isSchemaRule(rule) && value && typeof value === 'object') {\n return (\n Object.keys(rule.args[0]).length === Object.keys(value).length &&\n result\n );\n }\n return result;\n })\n .catch(() => false),\n },\n};\n\nfunction isSchemaRule(rule) {\n return (\n rule &&\n rule.name === 'schema' &&\n rule.args.length > 0 &&\n typeof rule.args[0] === 'object'\n );\n}\n\nfunction split(value) {\n if (typeof value === 'string') {\n return value.split('');\n }\n return value;\n}\n\nconst availableRules = {\n // Value\n\n equal: expected => value => value == expected,\n\n exact: expected => value => value === expected,\n\n // Types\n\n number: (allowInfinite = true) => value =>\n typeof value === 'number' && (allowInfinite || isFinite(value)),\n\n integer: () => value => {\n const isInteger = Number.isInteger || isIntegerPolyfill;\n return isInteger(value);\n },\n\n numeric: () => value => !isNaN(parseFloat(value)) && isFinite(value),\n\n string: () => testType('string'),\n\n boolean: () => testType('boolean'),\n\n undefined: () => testType('undefined'),\n\n null: () => testType('null'),\n\n array: () => testType('array'),\n\n object: () => testType('object'),\n\n instanceOf: instance => value => value instanceof instance,\n\n // Pattern\n\n pattern: expected => value => expected.test(value),\n\n lowercase: () => value => /^([a-z]+\\s*)+$/.test(value),\n\n uppercase: () => value => /^([A-Z]+\\s*)+$/.test(value),\n\n vowel: () => value => /^[aeiou]+$/i.test(value),\n\n consonant: () => value => /^(?=[^aeiou])([a-z]+)$/i.test(value),\n\n // Value at\n\n first: expected => value => value[0] == expected,\n\n last: expected => value => value[value.length - 1] == expected,\n\n // Length\n\n empty: () => value => value.length === 0,\n\n length: (min, max) => value =>\n value.length >= min && value.length <= (max || min),\n\n minLength: min => value => value.length >= min,\n\n maxLength: max => value => value.length <= max,\n\n // Range\n\n negative: () => value => value < 0,\n\n positive: () => value => value >= 0,\n\n between: (a, b) => value => value >= a && value <= b,\n\n range: (a, b) => value => value >= a && value <= b,\n\n lessThan: n => value => value < n,\n\n lessThanOrEqual: n => value => value <= n,\n\n greaterThan: n => value => value > n,\n\n greaterThanOrEqual: n => value => value >= n,\n\n // Divisible\n\n even: () => value => value % 2 === 0,\n\n odd: () => value => value % 2 !== 0,\n\n includes: expected => value => ~value.indexOf(expected),\n\n schema: schema => testSchema(schema),\n\n // branching\n\n passesAnyOf: (...validations) => value =>\n validations.some(validation => validation.test(value)),\n\n optional: createOptionalRule(false),\n optionalAsync: createOptionalRule(true),\n};\n\nfunction createOptionalRule(asynchronous) {\n return (validation, considerTrimmedEmptyString = false) => value => {\n if (\n considerTrimmedEmptyString &&\n typeof value === 'string' &&\n value.trim() === ''\n ) {\n return true;\n }\n\n if (value !== undefined && value !== null) {\n if (!asynchronous) {\n validation.check(value);\n } else {\n return validation.testAsync(value);\n }\n }\n return true;\n };\n}\n\nfunction testType(expected) {\n return value => {\n return (\n (Array.isArray(value) && expected === 'array') ||\n (value === null && expected === 'null') ||\n typeof value === expected\n );\n };\n}\n\nfunction isIntegerPolyfill(value) {\n return (\n typeof value === 'number' && isFinite(value) && Math.floor(value) === value\n );\n}\n\nfunction testSchema(schema) {\n return {\n simple: value => {\n const causes = [];\n Object.keys(schema).forEach(key => {\n const nestedValidation = schema[key];\n try {\n nestedValidation.check((value || {})[key]);\n } catch (ex) {\n ex.target = key;\n causes.push(ex);\n }\n });\n if (causes.length > 0) {\n throw causes;\n }\n return true;\n },\n async: value => {\n const causes = [];\n const nested = Object.keys(schema).map(key => {\n const nestedValidation = schema[key];\n return nestedValidation.testAsync((value || {})[key]).catch(ex => {\n ex.target = key;\n causes.push(ex);\n });\n });\n return Promise.all(nested).then(() => {\n if (causes.length > 0) {\n throw causes;\n }\n\n return true;\n });\n },\n };\n}\n\nexport default v8n;\n"],"names":["Rule","name","fn","args","modifiers","this","pickFn","variant","testAux","rule","length","const","modifier","shift","nextFn","perform","testAsyncAux","performAsync","value","Promise","resolve","_test","let","slice","ex","_check","it","_testAsync","reject","then","valid","catch","Modifier","ValidationError","cause","target","super","remaining","Error","captureStackTrace","Context","chain","nextRuleModifiers","executeAsyncRules","rules","v8n","undefined","Proxy","proxyContext","proxylessContext","_applyRule","ruleFn","push","apply","_applyModifier","simple","async","_clone","test","every","testAll","err","forEach","check","testAsync","customRules","context","get","obj","prop","newContext","availableModifiers","availableRules","addRuleSet","ruleSet","targetContext","Object","keys","contextWithRuleApplied","contextWithAvailableRules","contextWithAllRules","defineProperty","extend","newRules","assign","clearCustomRules","not","result","some","split","item","all","map","Boolean","strict","isSchemaRule","equal","expected","exact","number","allowInfinite","isFinite","integer","Number","isInteger","isIntegerPolyfill","numeric","isNaN","parseFloat","string","testType","boolean","null","array","object","instanceOf","instance","pattern","lowercase","uppercase","vowel","consonant","first","last","empty","min","max","minLength","maxLength","negative","positive","between","a","b","range","lessThan","n","lessThanOrEqual","greaterThan","greaterThanOrEqual","even","odd","includes","indexOf","schema","causes","key","nestedValidation","nested","testSchema","passesAnyOf","validations","validation","optional","createOptionalRule","optionalAsync","asynchronous","considerTrimmedEmptyString","trim","Array","isArray","Math","floor"],"mappings":"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"} \ No newline at end of file diff --git a/dist/v8n.system.js b/dist/v8n.system.js index cac9053..620a32e 100644 --- a/dist/v8n.system.js +++ b/dist/v8n.system.js @@ -16,13 +16,13 @@ System.register('v8n', [], function (exports) { var fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = function () { return false; }; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex$1) { return false; } @@ -30,14 +30,14 @@ System.register('v8n', [], function (exports) { Rule.prototype._check = function _check (value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), function (it) { return it; })(false)) { + if (testAux(this.modifiers.slice(), function (it) { return it; }, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } }; @@ -48,7 +48,8 @@ System.register('v8n', [], function (exports) { return new Promise(function (resolve, reject) { testAsyncAux( this$1.modifiers.slice(), - this$1.fn + this$1.fn, + this$1 )(value) .then(function (valid) { if (valid) { @@ -67,21 +68,21 @@ System.register('v8n', [], function (exports) { return typeof fn === 'object' ? fn[variant] : fn; } - function testAux(modifiers, fn) { + function testAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + var nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } - function testAsyncAux(modifiers, fn) { + function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + var nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return function (value) { return Promise.resolve(pickFn(fn, 'async')(value)); }; } @@ -309,8 +310,40 @@ System.register('v8n', [], function (exports) { simple: function (fn) { return function (value) { return value !== false && split(value).every(fn); }; }, async: function (fn) { return function (value) { return Promise.all(split(value).map(fn)).then(function (result) { return result.every(Boolean); }); }; }, }, + + strict: { + simple: function (fn, rule) { return function (value) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }; }, + async: function (fn, rule) { return function (value) { return Promise.resolve(fn(value)) + .then(function (result) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(function () { return false; }); }; }, + }, }; + function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); + } + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/dist/v8n.umd.js b/dist/v8n.umd.js index 24e98e7..1377752 100644 --- a/dist/v8n.umd.js +++ b/dist/v8n.umd.js @@ -15,13 +15,13 @@ var fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = function () { return false; }; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex$1) { return false; } @@ -29,14 +29,14 @@ Rule.prototype._check = function _check (value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), function (it) { return it; })(false)) { + if (testAux(this.modifiers.slice(), function (it) { return it; }, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } }; @@ -47,7 +47,8 @@ return new Promise(function (resolve, reject) { testAsyncAux( this$1.modifiers.slice(), - this$1.fn + this$1.fn, + this$1 )(value) .then(function (valid) { if (valid) { @@ -66,21 +67,21 @@ return typeof fn === 'object' ? fn[variant] : fn; } - function testAux(modifiers, fn) { + function testAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + var nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } - function testAsyncAux(modifiers, fn) { + function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { var modifier = modifiers.shift(); - var nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + var nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return function (value) { return Promise.resolve(pickFn(fn, 'async')(value)); }; } @@ -308,8 +309,40 @@ simple: function (fn) { return function (value) { return value !== false && split(value).every(fn); }; }, async: function (fn) { return function (value) { return Promise.all(split(value).map(fn)).then(function (result) { return result.every(Boolean); }); }; }, }, + + strict: { + simple: function (fn, rule) { return function (value) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }; }, + async: function (fn, rule) { return function (value) { return Promise.resolve(fn(value)) + .then(function (result) { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(function () { return false; }); }; }, + }, }; + function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); + } + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/docs/api/README.md b/docs/api/README.md index 6cb244c..9cfe9ff 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -79,15 +79,16 @@ sidebar: auto - **Properties:** - - `fork: Function` - - `exec: Function` + - `name: string` + - `perform: Function` + - `performAsync: Function` - **Details:** This class represents a modifier. It is contained in an array within the - `modifiers` property of a [`Rule`](#rule). `fork` is a helper function for - mapping the value to the function correctly. `exec` performs the actual - modification of the modifier. + `modifiers` property of a [`Rule`](#rule). The functions `perform` and + `performAsync` are used to apply the modifier to a rule depending on the + validation strategy required. - **See also:** [Rule](#rule) @@ -1037,6 +1038,12 @@ sidebar: auto values of the given object are then validated based on the validation specified for it's key in the schema. + ::: info + Schemas are validated like interfaces. That means, while they enforce that the + given schema is met, it also allows additional properties on the object. This + behaviour can be changed by using the [`strict`](#strict) modifier. + ::: + ```js const validation = v8n().schema({ id: v8n() @@ -1234,3 +1241,33 @@ This rule is asynchronous and requires the [`testAsync` validation strategy](#te .every.positive() .test(1, 2, -3); // false ``` + +### strict + +- **Applicable Types:** `object` + +- **Applicable Rules:** `schema` + +- **Usage:** + + This modifier makes checks for object schemas strict. This means that + the schema must match the object exactly and no extraneous properties + may be included. For other rules this modifier will not have any effect. + + ```js + v8n() + .strict.schema({ + id: v8n() + .number() + .positive(), + }) + .test({ id: 2 }); // true + + v8n() + .strict.schema({ + id: v8n() + .number() + .positive(), + }) + .test({ id: 2, name: 'Luke' }); // false + ``` diff --git a/src/Rule.js b/src/Rule.js index 4f290a3..47ffd3d 100644 --- a/src/Rule.js +++ b/src/Rule.js @@ -10,13 +10,13 @@ class Rule { let fn = this.fn; try { - testAux(this.modifiers.slice(), fn)(value); + testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { fn = () => false; } try { - return testAux(this.modifiers.slice(), fn)(value); + return testAux(this.modifiers.slice(), fn, this)(value); } catch (ex) { return false; } @@ -24,14 +24,14 @@ class Rule { _check(value) { try { - testAux(this.modifiers.slice(), this.fn)(value); + testAux(this.modifiers.slice(), this.fn, this)(value); } catch (ex) { - if (testAux(this.modifiers.slice(), it => it)(false)) { + if (testAux(this.modifiers.slice(), it => it, this)(false)) { return; } } - if (!testAux(this.modifiers.slice(), this.fn)(value)) { + if (!testAux(this.modifiers.slice(), this.fn, this)(value)) { throw null; } } @@ -41,6 +41,7 @@ class Rule { testAsyncAux( this.modifiers.slice(), this.fn, + this, )(value) .then(valid => { if (valid) { @@ -58,21 +59,21 @@ function pickFn(fn, variant = 'simple') { return typeof fn === 'object' ? fn[variant] : fn; } -function testAux(modifiers, fn) { +function testAux(modifiers, fn, rule) { if (modifiers.length) { const modifier = modifiers.shift(); - const nextFn = testAux(modifiers, fn); - return modifier.perform(nextFn); + const nextFn = testAux(modifiers, fn, rule); + return modifier.perform(nextFn, rule); } else { return pickFn(fn); } } -function testAsyncAux(modifiers, fn) { +function testAsyncAux(modifiers, fn, rule) { if (modifiers.length) { const modifier = modifiers.shift(); - const nextFn = testAsyncAux(modifiers, fn); - return modifier.performAsync(nextFn); + const nextFn = testAsyncAux(modifiers, fn, rule); + return modifier.performAsync(nextFn, rule); } else { return value => Promise.resolve(pickFn(fn, 'async')(value)); } diff --git a/src/v8n.js b/src/v8n.js index be23851..589d347 100644 --- a/src/v8n.js +++ b/src/v8n.js @@ -109,8 +109,41 @@ const availableModifiers = { async: fn => value => Promise.all(split(value).map(fn)).then(result => result.every(Boolean)), }, + + strict: { + simple: (fn, rule) => value => { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + fn(value) + ); + } + return fn(value); + }, + async: (fn, rule) => value => + Promise.resolve(fn(value)) + .then(result => { + if (isSchemaRule(rule) && value && typeof value === 'object') { + return ( + Object.keys(rule.args[0]).length === Object.keys(value).length && + result + ); + } + return result; + }) + .catch(() => false), + }, }; +function isSchemaRule(rule) { + return ( + rule && + rule.name === 'schema' && + rule.args.length > 0 && + typeof rule.args[0] === 'object' + ); +} + function split(value) { if (typeof value === 'string') { return value.split(''); diff --git a/src/v8n.test.js b/src/v8n.test.js index 9c6a748..8ddec8d 100644 --- a/src/v8n.test.js +++ b/src/v8n.test.js @@ -451,6 +451,160 @@ describe('modifiers', () => { }); }); + describe("the 'strict' modifier", () => { + it('makes the schema rule strict', () => { + const validation = v8n().strict.schema({ + id: v8n() + .number() + .positive(), + name: v8n() + .string() + .minLength(4), + }); + + expect( + validation.test({ + id: 1, + name: 'Luke', + }), + ).toBeTruthy(); + + expect( + validation.test({ + id: 1, + }), + ).toBeFalsy(); + + expect( + validation.test({ + id: 1, + name: 'Luke', + lastname: 'Skywalker', + }), + ).toBeFalsy(); + }); + + it('makes the schema rule strict asynchronously', async () => { + v8n.extend({ asyncRule }); + + const validation = v8n().strict.schema({ + id: v8n() + .number() + .asyncRule([10, 20]), + }); + + const valid = { + id: 10, + }; + + const invalidValue = { + id: 1, + }; + + const invalidExtraProp = { + id: 1, + name: 'Luke', + }; + + await expect(validation.testAsync(valid)).resolves.toBe(valid); + await expect(validation.testAsync(invalidValue)).rejects.toBeInstanceOf( + ValidationError, + ); + await expect( + validation.testAsync(invalidExtraProp), + ).rejects.toBeInstanceOf(ValidationError); + }); + + it('does not affect non-schema validations', () => { + expect( + v8n() + .strict.number() + .test(1), + ).toEqual( + v8n() + .number() + .test(1), + ); + + expect( + v8n() + .strict.lowercase() + .test('abc'), + ).toEqual( + v8n() + .lowercase() + .test('abc'), + ); + }); + + it('can be chained with other modifiers', () => { + const schema = { + id: v8n() + .number() + .positive(), + }; + + expect( + v8n() + .not.strict.schema(schema) + .test({ + id: 1, + }), + ).toBeFalsy(); + + expect( + v8n() + .not.strict.schema(schema) + .test({ + id: 1, + name: 'abc', + }), + ).toBeTruthy(); + + expect( + v8n() + .some.strict.schema(schema) + .test([ + { + id: 1, + name: 'abc', + }, + { + id: 1, + }, + ]), + ).toBeTruthy(); + + expect( + v8n() + .some.strict.schema(schema) + .test([ + { + id: 1, + name: 'abc', + }, + { + id: -1, + }, + ]), + ).toBeFalsy(); + + expect( + v8n() + .not.some.strict.schema(schema) + .test([ + { + id: 1, + name: 'abc', + }, + { + id: 1, + }, + ]), + ).toBeFalsy(); + }); + }); + test('should be able to mix modifiers', () => { const validation = v8n().not.some.positive(); expect(validation.test([-1, -2, 1])).toBeFalsy(); diff --git a/types/modifier.d.ts b/types/modifier.d.ts index 3c8bf6e..2a5c385 100644 --- a/types/modifier.d.ts +++ b/types/modifier.d.ts @@ -1,6 +1,6 @@ -import { AsyncValidator, SimpleValidator } from './rule'; +import { AsyncValidator, SimpleValidator, Rule } from './rule'; -export type Performer = (fn: T) => T; +export type Performer = (fn: T, rule?: Rule) => T; export interface Modifier { name: string; diff --git a/types/test/test-v8n.ts b/types/test/test-v8n.ts index e1f0176..bc4adf3 100644 --- a/types/test/test-v8n.ts +++ b/types/test/test-v8n.ts @@ -35,7 +35,7 @@ v8n() .even() .odd() .includes('test') - .schema({ test: 2 }) + .strict.schema({ test: 2 }) .passesAnyOf() .optional(v8n().string()) .test(12); diff --git a/types/v8n.d.ts b/types/v8n.d.ts index 02070cd..1ecbfee 100644 --- a/types/v8n.d.ts +++ b/types/v8n.d.ts @@ -10,6 +10,7 @@ export interface V8nValidator { not: V8nValidator; some: V8nValidator; every: V8nValidator; + strict: V8nValidator; equal(expected: any): V8nValidator; exact(expected: any): V8nValidator; number(allowInfinite?: boolean): V8nValidator;