From 3b9363fb72fca4b18f10ae1378e0bab9af4d8cfb Mon Sep 17 00:00:00 2001 From: ealush Date: Tue, 11 Jun 2019 15:19:10 +0300 Subject: [PATCH] [Minor] add .cancel() callback --- CHANGELOG.md | 2 + config/test-setup.js | 3 +- dist/passable.js | 84 ++++++++++++++-------- dist/passable.js.map | 2 +- dist/passable.min.js | 2 +- dist/passable.min.js.map | 2 +- documentation/getting_started/callbacks.md | 50 ++++++++----- src/core/Passable/index.js | 64 +++++++++++------ src/core/passableResult/index.js | 26 +++++-- src/core/passableResult/spec.js | 72 ++++++++++++++++++- src/types.js | 5 +- 11 files changed, 230 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e2799c1..47d378fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - [Major] Lowercased library name when imported on global object. - [Major] Renamed `validationErrors` and `validationWarnings` output properties to `errors` and `warnings`. +- [Patch] Guarantee that `.done()` callbacks only run once. ### Added - [Minor] `.after()` callback that can run after a specific field finished execution. @@ -16,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - [Minor] New size rules (`longerThan`, `shorterThan`, `longerThanOrEquals`, `shorterThanOrEquals`, `lengthEquals`, `lengthNotEquals`). - [Minor] New content rules (`equals`, `notEquals`). - [Minor] Support returning promise from test callback for async tests. +- [Minor] Add cancel callback. ### Removed - [Major] Removed output properties: `hasValidationErrors`, `hasValidationWarnings`. diff --git a/config/test-setup.js b/config/test-setup.js index f02bfc57..25640fd5 100644 --- a/config/test-setup.js +++ b/config/test-setup.js @@ -10,7 +10,8 @@ export const excludeFromResult = [ 'getErrors', 'hasErrors', 'hasWarnings', - 'getWarnings' + 'getWarnings', + 'cancel' ]; global.PASSABLE_VERSION = require('../package.json').version; \ No newline at end of file diff --git a/dist/passable.js b/dist/passable.js index ff9040b2..f7dfea2a 100644 --- a/dist/passable.js +++ b/dist/passable.js @@ -104,6 +104,7 @@ var asyncObject = null; var hasValidationErrors = false; var hasValidationWarnings = false; + var cancelled = false; /** * Initializes specific field's counters * @param {string} fieldName - The name of the field. @@ -195,7 +196,7 @@ var runCompletionCallbacks = function runCompletionCallbacks() { completionCallbacks.forEach(function (cb) { - return cb(output); + return !cancelled && cb(output); }); }; /** @@ -219,16 +220,18 @@ var markAsDone = function markAsDone(fieldName) { + if (!fieldName) { + return runCompletionCallbacks(); + } + if (asyncObject !== null && asyncObject[fieldName]) { asyncObject[fieldName].done = true; // run field callbacks set in `after` if (asyncObject[fieldName].callbacks) { asyncObject[fieldName].callbacks.forEach(function (callback) { - return callback(output); + return !cancelled && callback(output); }); } - - runCompletionCallbacks(); } }; /** @@ -274,6 +277,15 @@ return output; }; + /** + * cancels done/after callbacks. They won't invoke when async operations complete + */ + + + var cancel = function cancel() { + cancelled = true; + return output; + }; /** * Gets all the errors of a field, or of the whole object * @param {string} [fieldName] - The name of the field. @@ -353,7 +365,8 @@ getErrors: getErrors, getWarnings: getWarnings, done: done, - after: after + after: after, + cancel: cancel }; return { initFieldCounters: initFieldCounters, @@ -513,9 +526,17 @@ }); _defineProperty(this, "hasRemainingPendingTests", function (fieldName) { - return _this.pending.some(function (test) { - return test.fieldName === fieldName; - }); + if (!_this.pending.length) { + return false; + } + + if (fieldName) { + return _this.pending.some(function (test) { + return test.fieldName === fieldName; + }); + } + + return !!_this.pending.length; }); _defineProperty(this, "test", function (fieldName, statement, test, severity) { @@ -544,27 +565,12 @@ }); _defineProperty(this, "runTest", function (test) { - var _test = test, - fieldName = _test.fieldName, - statement = _test.statement, - severity = _test.severity; + var fieldName = test.fieldName, + statement = test.statement, + severity = test.severity; var isAsync = typeof test.then === 'function'; var testResult; - if (!isAsync) { - try { - testResult = test(); - } catch (e) { - testResult = false; - } - - if (testResult && typeof testResult.then === 'function') { - isAsync = true; // $FlowFixMe - - test = testResult; - } - } - if (isAsync) { _this.res.markAsync(fieldName); @@ -574,11 +580,17 @@ if (!_this.hasRemainingPendingTests(fieldName)) { _this.res.markAsDone(fieldName); } + + if (!_this.hasRemainingPendingTests()) { + _this.res.markAsDone(); + } }; var fail = function fail() { // order is important here! fail needs to be called before `done`. - _this.res.fail(fieldName, statement, severity); + if (_this.pending.includes(test)) { + _this.res.fail(fieldName, statement, severity); + } done(); }; @@ -587,9 +599,25 @@ // $FlowFixMe test.then(done, fail); } catch (e) { - fail(); + fail(test); } } else { + try { + testResult = test(); + } catch (e) { + testResult = false; + } // if is async after all + + + if (testResult && typeof testResult.then === 'function') { + testResult.fieldName = fieldName; + testResult.statement = statement; + testResult.severity = severity; // $FlowFixMe + + return _this.addPendingTest(testResult); + } // explicitly false + + if (testResult === false) { _this.res.fail(fieldName, statement, severity); } diff --git a/dist/passable.js.map b/dist/passable.js.map index b92d9598..69eca6f5 100644 --- a/dist/passable.js.map +++ b/dist/passable.js.map @@ -1 +1 @@ -{"version":3,"file":"passable.js","sources":["../src/constants.js","../src/core/passableResult/index.js","../src/core/Specific/index.js","../src/core/Passable/index.js","../src/Enforce/runnables/rules/is_array/index.js","../src/Enforce/runnables/rules/is_number/index.js","../src/Enforce/runnables/rules/is_string/index.js","../src/Enforce/runnables/rules/matches/index.js","../src/Enforce/runnables/rules/inside/index.js","../src/Enforce/runnables/rules/equals/index.js","../src/Enforce/runnables/rules/is_numeric/index.js","../src/Enforce/runnables/rules/is_empty/index.js","../src/Enforce/runnables/rules/greater_than/index.js","../src/Enforce/runnables/rules/greater_than_or_equals/index.js","../src/Enforce/runnables/rules/less_than/index.js","../src/Enforce/runnables/rules/less_than_or_equals/index.js","../src/Enforce/runnables/rules/longer_than/index.js","../src/Enforce/runnables/rules/longer_than_or_equals/index.js","../src/Enforce/runnables/rules/shorter_than/index.js","../src/Enforce/runnables/rules/shorter_than_or_equals/index.js","../src/Enforce/runnables/rules/length_equals/index.js","../src/Enforce/runnables/helpers/extend_rules/index.js","../src/Enforce/runnables/index.js","../src/Enforce/runners/rule/index.js","../src/Enforce/index.js","../src/validate/index.js","../src/index.js"],"sourcesContent":["// @flow\n\nexport const WARN: Severity = 'warn';\nexport const FAIL: Severity = 'fail';","// @flow\n\nimport { WARN, FAIL } from '../../constants';\nconst severities: string[] = [ WARN, FAIL ];\n\ntype AsyncObject = null | {\n [fieldName: string]: {\n done: boolean,\n callbacks: Function[]\n }\n};\n\nconst passableResult: Function = (name: string): PassableResult => {\n\n const completionCallbacks: Function[] = [];\n let asyncObject: AsyncObject = null;\n let hasValidationErrors: boolean = false;\n let hasValidationWarnings: boolean = false;\n\n /**\n * Initializes specific field's counters\n * @param {string} fieldName - The name of the field.\n */\n const initFieldCounters: Function = (fieldName: string) => {\n if (output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName] = {\n testCount: 0,\n failCount: 0,\n warnCount: 0\n };\n };\n\n /**\n * Bumps test counters to indicate tests that's being performed\n * @param {string} fieldName - The name of the field.\n */\n const bumpTestCounter: Function = (fieldName: string) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName].testCount++;\n output.testCount++;\n };\n\n /**\n * Bumps field's warning counts and adds warning string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestWarning: Function = (fieldName: string, statement: string) => {\n hasValidationWarnings = true;\n output.warnings[fieldName] = output.warnings[fieldName] || [];\n output.warnings[fieldName].push(statement);\n output.warnCount++;\n output.testsPerformed[fieldName].warnCount++;\n };\n\n /**\n * Bumps field's error counts and adds error string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestError: Function = (fieldName: string, statement: string) => {\n hasValidationErrors = true;\n output.errors[fieldName] = output.errors[fieldName] || [];\n output.errors[fieldName].push(statement);\n output.failCount++;\n output.testsPerformed[fieldName].failCount++;\n };\n\n /**\n * Fails a field and updates output accordingly\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n * @param {string} severity - Whether it is a `fail` or `warn` test.\n */\n const fail: Function = (fieldName: string, statement: string, severity: Severity) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n const selectedSeverity: Severity = severity && severities.includes(severity) ? severity : FAIL;\n\n selectedSeverity === WARN\n ? bumpTestWarning(fieldName, statement)\n : bumpTestError(fieldName, statement);\n };\n\n /**\n * Uniquely add a field to the `skipped` list\n * @param {string} fieldName\n */\n const addToSkipped: Function = (fieldName: string) => {\n !output.skipped.includes(fieldName) && output.skipped.push(fieldName);\n };\n\n /**\n * Runs completion callbacks aggregated by `done`\n * regardless of success or failure\n */\n const runCompletionCallbacks: Function = () => {\n completionCallbacks.forEach((cb) => cb(output));\n };\n\n /**\n * Marks a field as async\n * @param {string} fieldName the name of the field marked as async\n */\n const markAsync: Function = (fieldName: string) => {\n asyncObject = asyncObject || {};\n asyncObject[fieldName] = asyncObject[fieldName] || {};\n asyncObject[fieldName] = {\n done: false,\n callbacks: asyncObject[fieldName].callbacks || []\n };\n };\n\n /**\n * Marks an async field as done\n * @param {string} fieldName the name of the field marked as done\n */\n const markAsDone: Function = (fieldName: string) => {\n if (asyncObject !== null && asyncObject[fieldName]) {\n asyncObject[fieldName].done = true;\n\n // run field callbacks set in `after`\n if (asyncObject[fieldName].callbacks) {\n asyncObject[fieldName].callbacks.forEach((callback) => callback(output));\n }\n\n runCompletionCallbacks();\n }\n };\n\n /**\n * Registers callback functions to be run when test suite is done running\n * If current suite is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const done: Function = (callback: Function) => {\n if (typeof callback !== 'function') {return output;}\n\n if (!asyncObject) {\n callback(output);\n }\n\n completionCallbacks.push(callback);\n return output;\n };\n\n /**\n * Registers callback functions to be run when a certain field is done running\n * If field is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const after: Function = (fieldName: string, callback) => {\n if (typeof callback !== 'function') {\n return output;\n }\n\n asyncObject = asyncObject || {};\n if (!asyncObject[fieldName] && output.testsPerformed[fieldName]) {\n callback(output);\n } else if (asyncObject[fieldName]) {\n asyncObject[fieldName].callbacks = [...(asyncObject[fieldName].callbacks || []), callback];\n }\n\n return output;\n };\n\n /**\n * Gets all the errors of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's errors, or all errors\n */\n const getErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.errors;\n }\n\n if (output.errors[fieldName]) {\n return output.errors[fieldName];\n }\n\n return [];\n };\n\n /**\n * Gets all the warnings of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's warnings, or all warnings\n */\n const getWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.warnings;\n }\n\n if (output.warnings[fieldName]) {\n return output.warnings[fieldName];\n }\n\n return [];\n };\n\n /**\n * Checks if a certain field (or the whole suite) has errors\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationErrors;\n }\n\n return Boolean(output.getErrors(fieldName).length);\n };\n\n /**\n * Checks if a certain field (or the whole suite) has warnings\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationWarnings;\n }\n\n return Boolean(output.getWarnings(fieldName).length);\n };\n\n const output: PassableOutput = {\n name,\n failCount: 0,\n warnCount: 0,\n testCount: 0,\n testsPerformed: {},\n errors: {},\n warnings: {},\n skipped: [],\n hasErrors,\n hasWarnings,\n getErrors,\n getWarnings,\n done,\n after\n };\n\n return {\n initFieldCounters,\n bumpTestError,\n bumpTestWarning,\n bumpTestCounter,\n fail,\n addToSkipped,\n runCompletionCallbacks,\n markAsync,\n markAsDone,\n output\n };\n};\n\nexport default passableResult;","// @flow\n\n/** Class representing validation inclusion and exclusion groups */\nclass Specific {\n not: SpecificGroup;\n only: SpecificGroup;\n\n /**\n * Initialize Specific object\n *\n * @param {String | Array | Object | undefined} specific\n */\n constructor(specific: ?SpecificArgs) {\n\n if (!specific) { return; }\n\n if (!Specific.is(specific)) {\n throw new TypeError();\n }\n\n if (typeof specific === 'string' || Array.isArray(specific)) {\n if (specific.length === 0) { return; }\n this.only = this.populateGroup(this.only, specific);\n return;\n }\n\n if (specific.only) {\n this.only = this.populateGroup(this.only, specific.only);\n }\n\n if (specific.not) {\n this.not = this.populateGroup(this.not, specific.not);\n }\n }\n\n /**\n * Populate inclusion and exclusion groups\n *\n * @param {Object} group - the group to populate.\n * @param {String | Array} field - the field to add to the group\n * @return {Object} modified group\n */\n populateGroup(group: SpecificGroup, field: SpecificField) {\n group = group || {};\n\n if (typeof field === 'string') {\n group[field] = true;\n } else if (Array.isArray(field)) {\n field.forEach((item) => group[item] = true);\n }\n\n return group;\n }\n\n /**\n * Checkes whether a given field name is in exclusion group\n * or not a member of inclusion group (when present)\n *\n * @param {String} fieldName\n * @return {Boolean}\n */\n excludes(fieldName: string) {\n if (this.only && !this.only[fieldName]) {\n return true;\n }\n\n if (this.not && this.not[fieldName]) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Test whether a given argument matches\n * the `specific` filter convention\n *\n * @param {Any} item\n * @return {boolean}\n */\n static is(item: AnyValue) {\n if (Array.isArray(item)) {\n return item.every((item) => typeof item === 'string');\n }\n\n if (typeof item === 'string') { return true; }\n\n if (item !== null && typeof item === 'object' && (\n item.hasOwnProperty('only')\n || item.hasOwnProperty('not')\n )) {\n return true;\n }\n\n return false;\n }\n}\n\nexport default Specific;","// @flow\n\nimport passableResult from '../passableResult';\nimport Specific from '../Specific';\n\nconst constructorError: Function = (name: string, value: string, doc?: string): string => `[Passable]: failed during suite initialization. Unexpected '${typeof value}' for '${name}' argument.\n See: ${doc ? doc : 'https://fiverr.github.io/passable/getting_started/writing_tests.html'}`;\n\n/**\n * Describes a passable validation suite\n */\nclass Passable {\n specific: Specific;\n res: PassableResult;\n test: TestProvider;\n pending: Array;\n\n pending = [];\n\n /**\n * Initializes a validation suite, creates a new passableResult instance and runs pending tests\n */\n constructor(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n\n if (typeof name !== 'string') {\n throw new TypeError(constructorError('suite name', name));\n }\n\n if (typeof tests !== 'function') {\n throw new TypeError(constructorError('tests', tests));\n }\n\n if (specific && !Specific.is(specific)) {\n throw new TypeError(constructorError('specific', tests, 'https://fiverr.github.io/passable/test/specific.html'));\n }\n\n this.specific = new Specific(specific);\n\n this.res = passableResult(name);\n\n tests(this.test, this.res.output);\n this.runPendingTests();\n }\n\n addPendingTest = (test: PassableTest) => this.pending.push(test);\n\n clearPendingTest = (test: PassableTest) => {\n this.pending = (this.pending.filter((t: PassableTest): boolean => t !== test): Array);\n };\n\n /**\n * Checks if a given field name still has pending tests\n * @param {String} fieldName name of the field to test against\n * @return {Boolean}\n */\n hasRemainingPendingTests = (fieldName: string) => this.pending.some((test) => test.fieldName === fieldName);\n\n /**\n * Test function passed over to the consumer.\n * It initiates field validation, and adds te test to the pending tests list\n * @param {string} fieldName the name of the field being validated\n * @param {string} statement description of the test\n * @param {function | Promise} test the actual test callback or promise\n */\n test = (fieldName: string, statement: string, test: PassableTest, severity: Severity) => {\n\n if (this.specific.excludes(fieldName)) {\n this.res.addToSkipped(fieldName);\n return;\n }\n\n this.res.initFieldCounters(fieldName);\n\n let operation: Function;\n\n if (typeof test === 'function') {\n operation = this.runTest;\n } else if (test instanceof Promise) {\n operation = this.addPendingTest;\n } else {\n return;\n }\n\n test.fieldName = fieldName;\n test.statement = statement;\n test.severity = severity;\n\n operation(test);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n * @param {function | Promise} test the actual test callback or promise\n */\n runTest = (test: PassableTest) => {\n\n const {\n fieldName,\n statement,\n severity\n }: {\n severity: Severity,\n fieldName: string,\n statement: string\n } = test;\n\n let isAsync: boolean = typeof test.then === 'function';\n let testResult: AnyValue;\n\n\n if (!isAsync) {\n try {\n testResult = test();\n } catch (e) {\n testResult = false;\n }\n\n if (testResult && typeof testResult.then === 'function') {\n isAsync = true;\n\n // $FlowFixMe\n test = testResult;\n }\n }\n\n if (isAsync) {\n this.res.markAsync(fieldName);\n\n const done: Function = () => {\n this.clearPendingTest(test);\n if (!this.hasRemainingPendingTests(fieldName)) {\n this.res.markAsDone(fieldName);\n }\n };\n\n const fail: Function = () => {\n // order is important here! fail needs to be called before `done`.\n this.res.fail(fieldName, statement, severity);\n done();\n };\n\n try {\n // $FlowFixMe\n test.then(done, fail);\n } catch (e) {\n fail();\n }\n } else {\n\n if (testResult === false) {\n this.res.fail(fieldName, statement, severity);\n }\n this.clearPendingTest(test);\n }\n this.res.bumpTestCounter(fieldName);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n */\n runPendingTests = () => {\n [...this.pending].forEach(this.runTest);\n }\n}\n\nexport default Passable;","// @flow\n\nfunction isArray(value: mixed): boolean {\n return Boolean(Array.isArray(value));\n}\n\nisArray.negativeForm = 'isNotArray';\n\nexport default isArray;","// @flow\n\nfunction isNumber(value: mixed): boolean {\n return Boolean(typeof value === 'number');\n}\n\nisNumber.negativeForm = 'isNotNumber';\n\nexport default isNumber;","// @flow\n\nfunction isString(value: mixed): boolean {\n return Boolean(typeof value === 'string');\n}\n\nisString.negativeForm = 'isNotString';\n\nexport default isString;","// @flow\n\nfunction matches(value: string, regex: RegExp | string): boolean {\n\n if (regex instanceof RegExp) {\n return regex.test(value);\n } else if (typeof regex === 'string') {\n return new RegExp(regex).test(value);\n } else {\n return false;\n }\n}\n\nmatches.negativeForm = 'notMatches';\n\nexport default matches;","// @flow\n\ntype All = NumStrBool | Array;\ntype Value = All | Array;\ntype Arg = string | Array;\n\nfunction inside(value: Value, arg1: Arg): boolean {\n\n if (Array.isArray(arg1) && ['string', 'number', 'boolean'].includes(typeof value)) {\n return arg1.includes(value);\n }\n\n // both value and arg1 are strings\n if (typeof arg1 === 'string' && typeof value === 'string') {\n return arg1.includes(value);\n }\n\n return false;\n}\n\ninside.negativeForm = 'notInside';\n\nexport default inside;","// @flow\n\nfunction equals(value: AnyValue, arg1: AnyValue): boolean {\n return value === arg1;\n}\n\nequals.negativeForm = 'notEquals';\n\nexport default equals;","// @flow\n\nfunction isNumeric(value: mixed): boolean {\n const result: boolean = !isNaN(parseFloat(value)) && !isNaN(Number(value)) && isFinite(value);\n return Boolean(result);\n}\n\nisNumeric.negativeForm = 'isNotNumeric';\n\nexport default isNumeric;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction isEmpty(value: AnyValue): boolean {\n if (!value) {\n return true;\n } else if (isNumeric(value)) {\n return value === 0;\n } else if (value.hasOwnProperty('length')) {\n return value.length === 0;\n } else if (typeof value === 'object') {\n return Object.keys(value).length === 0;\n } else {\n return true;\n }\n};\n\nisEmpty.negativeForm = 'isNotEmpty';\n\nexport default isEmpty;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) > Number(arg1);\n}\n\ngreaterThan.alias = 'gt';\n\nexport default greaterThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) >= Number(arg1);\n}\n\ngreaterThanOrEquals.alias = 'gte';\n\nexport default greaterThanOrEquals;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) < Number(arg1);\n}\n\nlessThan.alias = 'lt';\n\nexport default lessThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) <= Number(arg1);\n}\n\nlessThanOrEquals.alias = 'lte';\n\nexport default lessThanOrEquals;","// @flow\n\nfunction longerThan(value: StringOrArray, arg1: number): boolean {\n return value.length > arg1;\n}\n\nexport default longerThan;\n","// @flow\n\nfunction longerThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length >= arg1;\n}\n\nexport default longerThanOrEquals;\n","// @flow\n\nfunction shorterThan(value: StringOrArray, arg1: number): boolean {\n return value.length < arg1;\n}\n\nexport default shorterThan;\n","// @flow\n\nfunction shorterThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length <= arg1;\n}\n\nexport default shorterThanOrEquals;\n","// @flow\n\nfunction lengthEquals(value: StringOrArray, arg1: number): boolean {\n return value.length === arg1;\n}\n\nlengthEquals.negativeForm = 'lengthNotEquals';\n\nexport default lengthEquals;\n","// @flow\n\n/**\n * Collects rules with `negativeForm` or `alias` attributes.\n * Adds a rule with the correct configuration.\n * @param {Object} rules - enforce rules object\n * @returns {Object} extended rules object\n */\nfunction extendRules(rules: EnforceRules) {\n\n for (const rule: string in rules) {\n const negativeForm: string = rules[rule].negativeForm;\n const alias: string = rules[rule].alias;\n\n if (negativeForm) {\n rules[negativeForm] = (...args) => !rules[rule](...args);\n }\n\n if (alias) {\n rules[alias] = rules[rule];\n }\n }\n\n return rules;\n}\n\nexport default extendRules;\n","// // @flow\n\nimport isArray from './rules/is_array';\nimport isNumber from './rules/is_number';\nimport isString from './rules/is_string';\nimport matches from './rules/matches';\nimport inside from './rules/inside';\nimport equals from './rules/equals';\nimport isNumeric from './rules/is_numeric';\nimport isEmpty from './rules/is_empty';\nimport greaterThan from './rules/greater_than';\nimport greaterThanOrEquals from './rules/greater_than_or_equals';\nimport lessThan from './rules/less_than';\nimport lessThanOrEquals from './rules/less_than_or_equals';\nimport longerThan from './rules/longer_than';\nimport longerThanOrEquals from './rules/longer_than_or_equals';\nimport shorterThan from './rules/shorter_than';\nimport shorterThanOrEquals from './rules/shorter_than_or_equals';\nimport lengthEquals from './rules/length_equals';\nimport extendRules from './helpers/extend_rules';\n\nconst rules: EnforceRules = {\n isArray,\n isNumber,\n isString,\n matches,\n inside,\n equals,\n isNumeric,\n isEmpty,\n greaterThan,\n greaterThanOrEquals,\n lessThan,\n lessThanOrEquals,\n longerThan,\n longerThanOrEquals,\n shorterThan,\n shorterThanOrEquals,\n lengthEquals\n};\n\nexport default extendRules(rules);","// @flow\n\n/**\n * Run a single rule against enforced value (e.g. `isNumber()`)\n *\n * @param {Function} rule - rule to run\n * @param {Any} value\n * @param {Array} args list of arguments sent from consumer\n */\nfunction rule(rule: EnforceRule, value: AnyValue, ...args: RuleArgs): void {\n\n if (typeof rule !== 'function') { return; }\n\n if (rule(value, ...args) !== true) {\n throw new Error(`[Enforce]: invalid ${typeof value} value`);\n }\n}\n\nexport default rule;\n","// @flow\n\nimport rules from './runnables';\nimport ruleRunner from './runners/rule';\n\n// $FlowFixMe\nconst glob: GlobalObject = Function('return this')();\n\nconst isRule: Function = (rulesObject, name): boolean => (\n rulesObject.hasOwnProperty(name) && typeof rulesObject[name] === 'function'\n);\n\nconst Enforce: Function = (customRules: EnforceRules = {}): EnforceInstance => {\n const rulesObject: EnforceRules = {...rules, ...customRules};\n\n if (typeof Proxy === 'function') {\n return (value: AnyValue): EnforceRules => {\n const proxy: EnforceRules = new Proxy(rulesObject, {\n get: (rules, fnName) => {\n if (!isRule(rules, fnName)) { return; }\n\n return (...args) => {\n ruleRunner(rules[fnName], value, ...args);\n return proxy;\n };\n }\n });\n return proxy;\n };\n }\n\n // This is relatively heavier, and preferably should only be done when lacking proxy support\n return (value) => Object.keys(rulesObject).reduce((allRules, fnName) => {\n if (!isRule(rulesObject, fnName)) { return allRules; }\n\n allRules[fnName] = (...args) => {\n ruleRunner(rulesObject[fnName], value, ...args);\n return allRules;\n };\n\n return allRules;\n }, {});\n};\n\nexport default Enforce;","// @flow\n\n/**\n * Run tests and catch errors\n *\n * @param {function} callback The test content\n * @return {boolean}\n */\nfunction validate(test: PassableTest): boolean {\n\n if (typeof test !== 'function' && !(test instanceof Promise)) {\n throw new TypeError(`[Validate]: expected ${typeof test} to be a function.`);\n }\n\n try {\n return test() !== false;\n } catch (_) {\n return false;\n }\n}\n\nexport default validate;","// @flow\nimport Passable from './core/Passable';\nimport Enforce from './Enforce';\nimport validate from './validate';\nimport { WARN, FAIL } from './constants';\n\nfunction passable(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n const suite: Passable = new Passable(name, tests, specific);\n return suite.res.output;\n}\n\npassable.VERSION = PASSABLE_VERSION;\npassable.enforce = new Enforce({});\npassable.Enforce = Enforce;\npassable.validate = validate;\npassable.WARN = WARN;\npassable.FAIL = FAIL;\n\nexport default passable;"],"names":["WARN","FAIL","severities","passableResult","name","completionCallbacks","asyncObject","hasValidationErrors","hasValidationWarnings","initFieldCounters","fieldName","output","testsPerformed","testCount","failCount","warnCount","bumpTestCounter","bumpTestWarning","statement","warnings","push","bumpTestError","errors","fail","severity","selectedSeverity","includes","addToSkipped","skipped","runCompletionCallbacks","forEach","cb","markAsync","done","callbacks","markAsDone","callback","after","getErrors","getWarnings","hasErrors","Boolean","length","hasWarnings","Specific","specific","is","TypeError","Array","isArray","only","populateGroup","not","group","field","item","every","hasOwnProperty","constructorError","value","doc","Passable","tests","test","pending","filter","t","some","excludes","res","operation","runTest","Promise","addPendingTest","isAsync","then","testResult","e","clearPendingTest","hasRemainingPendingTests","runPendingTests","negativeForm","isNumber","isString","matches","regex","RegExp","inside","arg1","equals","isNumeric","result","isNaN","parseFloat","Number","isFinite","isEmpty","Object","keys","greaterThan","alias","greaterThanOrEquals","lessThan","lessThanOrEquals","longerThan","longerThanOrEquals","shorterThan","shorterThanOrEquals","lengthEquals","extendRules","rules","rule","args","Error","glob","Function","isRule","rulesObject","Enforce","customRules","Proxy","proxy","get","fnName","ruleRunner","reduce","allRules","validate","_","passable","suite","VERSION","PASSABLE_VERSION","enforce"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"passable.js","sources":["../src/constants.js","../src/core/passableResult/index.js","../src/core/Specific/index.js","../src/core/Passable/index.js","../src/Enforce/runnables/rules/is_array/index.js","../src/Enforce/runnables/rules/is_number/index.js","../src/Enforce/runnables/rules/is_string/index.js","../src/Enforce/runnables/rules/matches/index.js","../src/Enforce/runnables/rules/inside/index.js","../src/Enforce/runnables/rules/equals/index.js","../src/Enforce/runnables/rules/is_numeric/index.js","../src/Enforce/runnables/rules/is_empty/index.js","../src/Enforce/runnables/rules/greater_than/index.js","../src/Enforce/runnables/rules/greater_than_or_equals/index.js","../src/Enforce/runnables/rules/less_than/index.js","../src/Enforce/runnables/rules/less_than_or_equals/index.js","../src/Enforce/runnables/rules/longer_than/index.js","../src/Enforce/runnables/rules/longer_than_or_equals/index.js","../src/Enforce/runnables/rules/shorter_than/index.js","../src/Enforce/runnables/rules/shorter_than_or_equals/index.js","../src/Enforce/runnables/rules/length_equals/index.js","../src/Enforce/runnables/helpers/extend_rules/index.js","../src/Enforce/runnables/index.js","../src/Enforce/runners/rule/index.js","../src/Enforce/index.js","../src/validate/index.js","../src/index.js"],"sourcesContent":["// @flow\n\nexport const WARN: Severity = 'warn';\nexport const FAIL: Severity = 'fail';","// @flow\n\nimport { WARN, FAIL } from '../../constants';\nconst severities: string[] = [ WARN, FAIL ];\n\ntype AsyncObject = null | {\n [fieldName: string]: {\n done: boolean,\n callbacks: Function[]\n }\n};\n\nconst passableResult: Function = (name: string): PassableResult => {\n\n const completionCallbacks: Function[] = [];\n let asyncObject: AsyncObject = null;\n let hasValidationErrors: boolean = false;\n let hasValidationWarnings: boolean = false;\n let cancelled: boolean = false;\n\n /**\n * Initializes specific field's counters\n * @param {string} fieldName - The name of the field.\n */\n const initFieldCounters: Function = (fieldName: string) => {\n if (output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName] = {\n testCount: 0,\n failCount: 0,\n warnCount: 0\n };\n };\n\n /**\n * Bumps test counters to indicate tests that's being performed\n * @param {string} fieldName - The name of the field.\n */\n const bumpTestCounter: Function = (fieldName: string) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName].testCount++;\n output.testCount++;\n };\n\n /**\n * Bumps field's warning counts and adds warning string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestWarning: Function = (fieldName: string, statement: string) => {\n hasValidationWarnings = true;\n output.warnings[fieldName] = output.warnings[fieldName] || [];\n output.warnings[fieldName].push(statement);\n output.warnCount++;\n output.testsPerformed[fieldName].warnCount++;\n };\n\n /**\n * Bumps field's error counts and adds error string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestError: Function = (fieldName: string, statement: string) => {\n hasValidationErrors = true;\n output.errors[fieldName] = output.errors[fieldName] || [];\n output.errors[fieldName].push(statement);\n output.failCount++;\n output.testsPerformed[fieldName].failCount++;\n };\n\n /**\n * Fails a field and updates output accordingly\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n * @param {string} severity - Whether it is a `fail` or `warn` test.\n */\n const fail: Function = (fieldName: string, statement: string, severity: Severity) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n const selectedSeverity: Severity = severity && severities.includes(severity) ? severity : FAIL;\n\n selectedSeverity === WARN\n ? bumpTestWarning(fieldName, statement)\n : bumpTestError(fieldName, statement);\n };\n\n /**\n * Uniquely add a field to the `skipped` list\n * @param {string} fieldName\n */\n const addToSkipped: Function = (fieldName: string) => {\n !output.skipped.includes(fieldName) && output.skipped.push(fieldName);\n };\n\n /**\n * Runs completion callbacks aggregated by `done`\n * regardless of success or failure\n */\n const runCompletionCallbacks: Function = () => {\n completionCallbacks.forEach((cb) => !cancelled && cb(output));\n };\n\n /**\n * Marks a field as async\n * @param {string} fieldName the name of the field marked as async\n */\n const markAsync: Function = (fieldName: string) => {\n asyncObject = asyncObject || {};\n asyncObject[fieldName] = asyncObject[fieldName] || {};\n asyncObject[fieldName] = {\n done: false,\n callbacks: asyncObject[fieldName].callbacks || []\n };\n };\n\n /**\n * Marks an async field as done\n * @param {string} fieldName the name of the field marked as done\n */\n const markAsDone: Function = (fieldName?: string) => {\n\n if (!fieldName) {\n return runCompletionCallbacks();\n }\n\n if (asyncObject !== null && asyncObject[fieldName]) {\n asyncObject[fieldName].done = true;\n\n // run field callbacks set in `after`\n if (asyncObject[fieldName].callbacks) {\n asyncObject[fieldName].callbacks.forEach((callback) => !cancelled && callback(output));\n }\n }\n };\n\n /**\n * Registers callback functions to be run when test suite is done running\n * If current suite is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const done: Function = (callback: Function) => {\n if (typeof callback !== 'function') {return output;}\n\n if (!asyncObject) {\n callback(output);\n }\n\n completionCallbacks.push(callback);\n return output;\n };\n\n /**\n * Registers callback functions to be run when a certain field is done running\n * If field is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const after: Function = (fieldName: string, callback) => {\n if (typeof callback !== 'function') {\n return output;\n }\n\n asyncObject = asyncObject || {};\n if (!asyncObject[fieldName] && output.testsPerformed[fieldName]) {\n callback(output);\n } else if (asyncObject[fieldName]) {\n asyncObject[fieldName].callbacks = [...(asyncObject[fieldName].callbacks || []), callback];\n }\n\n return output;\n };\n\n /**\n * cancels done/after callbacks. They won't invoke when async operations complete\n */\n const cancel: Function = () => {\n cancelled = true;\n\n return output;\n };\n\n /**\n * Gets all the errors of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's errors, or all errors\n */\n const getErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.errors;\n }\n\n if (output.errors[fieldName]) {\n return output.errors[fieldName];\n }\n\n return [];\n };\n\n /**\n * Gets all the warnings of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's warnings, or all warnings\n */\n const getWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.warnings;\n }\n\n if (output.warnings[fieldName]) {\n return output.warnings[fieldName];\n }\n\n return [];\n };\n\n /**\n * Checks if a certain field (or the whole suite) has errors\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationErrors;\n }\n\n return Boolean(output.getErrors(fieldName).length);\n };\n\n /**\n * Checks if a certain field (or the whole suite) has warnings\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationWarnings;\n }\n\n return Boolean(output.getWarnings(fieldName).length);\n };\n\n const output: PassableOutput = {\n name,\n failCount: 0,\n warnCount: 0,\n testCount: 0,\n testsPerformed: {},\n errors: {},\n warnings: {},\n skipped: [],\n hasErrors,\n hasWarnings,\n getErrors,\n getWarnings,\n done,\n after,\n cancel\n };\n\n return {\n initFieldCounters,\n bumpTestError,\n bumpTestWarning,\n bumpTestCounter,\n fail,\n addToSkipped,\n runCompletionCallbacks,\n markAsync,\n markAsDone,\n output\n };\n};\n\nexport default passableResult;","// @flow\n\n/** Class representing validation inclusion and exclusion groups */\nclass Specific {\n not: SpecificGroup;\n only: SpecificGroup;\n\n /**\n * Initialize Specific object\n *\n * @param {String | Array | Object | undefined} specific\n */\n constructor(specific: ?SpecificArgs) {\n\n if (!specific) { return; }\n\n if (!Specific.is(specific)) {\n throw new TypeError();\n }\n\n if (typeof specific === 'string' || Array.isArray(specific)) {\n if (specific.length === 0) { return; }\n this.only = this.populateGroup(this.only, specific);\n return;\n }\n\n if (specific.only) {\n this.only = this.populateGroup(this.only, specific.only);\n }\n\n if (specific.not) {\n this.not = this.populateGroup(this.not, specific.not);\n }\n }\n\n /**\n * Populate inclusion and exclusion groups\n *\n * @param {Object} group - the group to populate.\n * @param {String | Array} field - the field to add to the group\n * @return {Object} modified group\n */\n populateGroup(group: SpecificGroup, field: SpecificField) {\n group = group || {};\n\n if (typeof field === 'string') {\n group[field] = true;\n } else if (Array.isArray(field)) {\n field.forEach((item) => group[item] = true);\n }\n\n return group;\n }\n\n /**\n * Checkes whether a given field name is in exclusion group\n * or not a member of inclusion group (when present)\n *\n * @param {String} fieldName\n * @return {Boolean}\n */\n excludes(fieldName: string) {\n if (this.only && !this.only[fieldName]) {\n return true;\n }\n\n if (this.not && this.not[fieldName]) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Test whether a given argument matches\n * the `specific` filter convention\n *\n * @param {Any} item\n * @return {boolean}\n */\n static is(item: AnyValue) {\n if (Array.isArray(item)) {\n return item.every((item) => typeof item === 'string');\n }\n\n if (typeof item === 'string') { return true; }\n\n if (item !== null && typeof item === 'object' && (\n item.hasOwnProperty('only')\n || item.hasOwnProperty('not')\n )) {\n return true;\n }\n\n return false;\n }\n}\n\nexport default Specific;","// @flow\n\nimport passableResult from '../passableResult';\nimport Specific from '../Specific';\n\nconst constructorError: Function = (name: string, value: string, doc?: string): string => `[Passable]: failed during suite initialization. Unexpected '${typeof value}' for '${name}' argument.\n See: ${doc ? doc : 'https://fiverr.github.io/passable/getting_started/writing_tests.html'}`;\n\n/**\n * Describes a passable validation suite\n */\nclass Passable {\n specific: Specific;\n res: PassableResult;\n test: TestProvider;\n pending: Array = [];\n\n /**\n * Initializes a validation suite, creates a new passableResult instance and runs pending tests\n */\n constructor(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n\n if (typeof name !== 'string') {\n throw new TypeError(constructorError('suite name', name));\n }\n\n if (typeof tests !== 'function') {\n throw new TypeError(constructorError('tests', tests));\n }\n\n if (specific && !Specific.is(specific)) {\n throw new TypeError(constructorError('specific', tests, 'https://fiverr.github.io/passable/test/specific.html'));\n }\n\n this.specific = new Specific(specific);\n\n this.res = passableResult(name);\n\n tests(this.test, this.res.output);\n this.runPendingTests();\n }\n\n addPendingTest = (test: PassableTest) => this.pending.push(test);\n\n clearPendingTest = (test: PassableTest) => {\n this.pending = (this.pending.filter((t: PassableTest): boolean => t !== test): Array);\n };\n\n /**\n * Checks if a given field name still has pending tests\n * @param {String} fieldName name of the field to test against\n * @return {Boolean}\n */\n hasRemainingPendingTests = (fieldName?: string) => {\n if (!this.pending.length) {\n return false;\n }\n\n if (fieldName) {\n return this.pending.some((test) => test.fieldName === fieldName);\n }\n\n return !!this.pending.length;\n }\n\n /**\n * Test function passed over to the consumer.\n * It initiates field validation, and adds te test to the pending tests list\n * @param {string} fieldName the name of the field being validated\n * @param {string} statement description of the test\n * @param {function | Promise} test the actual test callback or promise\n */\n test = (fieldName: string, statement: string, test: PassableTest, severity: Severity) => {\n\n if (this.specific.excludes(fieldName)) {\n this.res.addToSkipped(fieldName);\n return;\n }\n\n this.res.initFieldCounters(fieldName);\n\n let operation: Function;\n\n if (typeof test === 'function') {\n operation = this.runTest;\n } else if (test instanceof Promise) {\n operation = this.addPendingTest;\n } else {\n return;\n }\n\n test.fieldName = fieldName;\n test.statement = statement;\n test.severity = severity;\n\n operation(test);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n * @param {function | Promise} test the actual test callback or promise\n */\n runTest = (test: PassableTest) => {\n\n const {\n fieldName,\n statement,\n severity\n }: {\n severity: Severity,\n fieldName: string,\n statement: string\n } = test;\n\n const isAsync: boolean = typeof test.then === 'function';\n let testResult: AnyValue;\n\n if (isAsync) {\n this.res.markAsync(fieldName);\n\n const done: Function = () => {\n this.clearPendingTest(test);\n if (!this.hasRemainingPendingTests(fieldName)) {\n this.res.markAsDone(fieldName);\n }\n\n if (!this.hasRemainingPendingTests()) {\n this.res.markAsDone();\n }\n };\n\n const fail: Function = () => {\n // order is important here! fail needs to be called before `done`.\n\n if (this.pending.includes(test)) {\n this.res.fail(fieldName, statement, severity);\n }\n done();\n };\n\n try {\n // $FlowFixMe\n test.then(done, fail);\n } catch (e) {\n fail(test);\n }\n } else {\n try {\n testResult = test();\n } catch (e) {\n testResult = false;\n }\n\n // if is async after all\n if (testResult && typeof testResult.then === 'function') {\n\n testResult.fieldName = fieldName;\n testResult.statement = statement;\n testResult.severity = severity;\n\n // $FlowFixMe\n return this.addPendingTest(testResult);\n }\n\n // explicitly false\n if (testResult === false) {\n this.res.fail(fieldName, statement, severity);\n }\n\n this.clearPendingTest(test);\n }\n\n this.res.bumpTestCounter(fieldName);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n */\n runPendingTests = () => {\n [...this.pending].forEach(this.runTest);\n }\n}\n\nexport default Passable;","// @flow\n\nfunction isArray(value: mixed): boolean {\n return Boolean(Array.isArray(value));\n}\n\nisArray.negativeForm = 'isNotArray';\n\nexport default isArray;","// @flow\n\nfunction isNumber(value: mixed): boolean {\n return Boolean(typeof value === 'number');\n}\n\nisNumber.negativeForm = 'isNotNumber';\n\nexport default isNumber;","// @flow\n\nfunction isString(value: mixed): boolean {\n return Boolean(typeof value === 'string');\n}\n\nisString.negativeForm = 'isNotString';\n\nexport default isString;","// @flow\n\nfunction matches(value: string, regex: RegExp | string): boolean {\n\n if (regex instanceof RegExp) {\n return regex.test(value);\n } else if (typeof regex === 'string') {\n return new RegExp(regex).test(value);\n } else {\n return false;\n }\n}\n\nmatches.negativeForm = 'notMatches';\n\nexport default matches;","// @flow\n\ntype All = NumStrBool | Array;\ntype Value = All | Array;\ntype Arg = string | Array;\n\nfunction inside(value: Value, arg1: Arg): boolean {\n\n if (Array.isArray(arg1) && ['string', 'number', 'boolean'].includes(typeof value)) {\n return arg1.includes(value);\n }\n\n // both value and arg1 are strings\n if (typeof arg1 === 'string' && typeof value === 'string') {\n return arg1.includes(value);\n }\n\n return false;\n}\n\ninside.negativeForm = 'notInside';\n\nexport default inside;","// @flow\n\nfunction equals(value: AnyValue, arg1: AnyValue): boolean {\n return value === arg1;\n}\n\nequals.negativeForm = 'notEquals';\n\nexport default equals;","// @flow\n\nfunction isNumeric(value: mixed): boolean {\n const result: boolean = !isNaN(parseFloat(value)) && !isNaN(Number(value)) && isFinite(value);\n return Boolean(result);\n}\n\nisNumeric.negativeForm = 'isNotNumeric';\n\nexport default isNumeric;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction isEmpty(value: AnyValue): boolean {\n if (!value) {\n return true;\n } else if (isNumeric(value)) {\n return value === 0;\n } else if (value.hasOwnProperty('length')) {\n return value.length === 0;\n } else if (typeof value === 'object') {\n return Object.keys(value).length === 0;\n } else {\n return true;\n }\n};\n\nisEmpty.negativeForm = 'isNotEmpty';\n\nexport default isEmpty;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) > Number(arg1);\n}\n\ngreaterThan.alias = 'gt';\n\nexport default greaterThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) >= Number(arg1);\n}\n\ngreaterThanOrEquals.alias = 'gte';\n\nexport default greaterThanOrEquals;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) < Number(arg1);\n}\n\nlessThan.alias = 'lt';\n\nexport default lessThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) <= Number(arg1);\n}\n\nlessThanOrEquals.alias = 'lte';\n\nexport default lessThanOrEquals;","// @flow\n\nfunction longerThan(value: StringOrArray, arg1: number): boolean {\n return value.length > arg1;\n}\n\nexport default longerThan;\n","// @flow\n\nfunction longerThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length >= arg1;\n}\n\nexport default longerThanOrEquals;\n","// @flow\n\nfunction shorterThan(value: StringOrArray, arg1: number): boolean {\n return value.length < arg1;\n}\n\nexport default shorterThan;\n","// @flow\n\nfunction shorterThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length <= arg1;\n}\n\nexport default shorterThanOrEquals;\n","// @flow\n\nfunction lengthEquals(value: StringOrArray, arg1: number): boolean {\n return value.length === arg1;\n}\n\nlengthEquals.negativeForm = 'lengthNotEquals';\n\nexport default lengthEquals;\n","// @flow\n\n/**\n * Collects rules with `negativeForm` or `alias` attributes.\n * Adds a rule with the correct configuration.\n * @param {Object} rules - enforce rules object\n * @returns {Object} extended rules object\n */\nfunction extendRules(rules: EnforceRules) {\n\n for (const rule: string in rules) {\n const negativeForm: string = rules[rule].negativeForm;\n const alias: string = rules[rule].alias;\n\n if (negativeForm) {\n rules[negativeForm] = (...args) => !rules[rule](...args);\n }\n\n if (alias) {\n rules[alias] = rules[rule];\n }\n }\n\n return rules;\n}\n\nexport default extendRules;\n","// // @flow\n\nimport isArray from './rules/is_array';\nimport isNumber from './rules/is_number';\nimport isString from './rules/is_string';\nimport matches from './rules/matches';\nimport inside from './rules/inside';\nimport equals from './rules/equals';\nimport isNumeric from './rules/is_numeric';\nimport isEmpty from './rules/is_empty';\nimport greaterThan from './rules/greater_than';\nimport greaterThanOrEquals from './rules/greater_than_or_equals';\nimport lessThan from './rules/less_than';\nimport lessThanOrEquals from './rules/less_than_or_equals';\nimport longerThan from './rules/longer_than';\nimport longerThanOrEquals from './rules/longer_than_or_equals';\nimport shorterThan from './rules/shorter_than';\nimport shorterThanOrEquals from './rules/shorter_than_or_equals';\nimport lengthEquals from './rules/length_equals';\nimport extendRules from './helpers/extend_rules';\n\nconst rules: EnforceRules = {\n isArray,\n isNumber,\n isString,\n matches,\n inside,\n equals,\n isNumeric,\n isEmpty,\n greaterThan,\n greaterThanOrEquals,\n lessThan,\n lessThanOrEquals,\n longerThan,\n longerThanOrEquals,\n shorterThan,\n shorterThanOrEquals,\n lengthEquals\n};\n\nexport default extendRules(rules);","// @flow\n\n/**\n * Run a single rule against enforced value (e.g. `isNumber()`)\n *\n * @param {Function} rule - rule to run\n * @param {Any} value\n * @param {Array} args list of arguments sent from consumer\n */\nfunction rule(rule: EnforceRule, value: AnyValue, ...args: RuleArgs): void {\n\n if (typeof rule !== 'function') { return; }\n\n if (rule(value, ...args) !== true) {\n throw new Error(`[Enforce]: invalid ${typeof value} value`);\n }\n}\n\nexport default rule;\n","// @flow\n\nimport rules from './runnables';\nimport ruleRunner from './runners/rule';\n\n// $FlowFixMe\nconst glob: GlobalObject = Function('return this')();\n\nconst isRule: Function = (rulesObject, name): boolean => (\n rulesObject.hasOwnProperty(name) && typeof rulesObject[name] === 'function'\n);\n\nconst Enforce: Function = (customRules: EnforceRules = {}): EnforceInstance => {\n const rulesObject: EnforceRules = {...rules, ...customRules};\n\n if (typeof Proxy === 'function') {\n return (value: AnyValue): EnforceRules => {\n const proxy: EnforceRules = new Proxy(rulesObject, {\n get: (rules, fnName) => {\n if (!isRule(rules, fnName)) { return; }\n\n return (...args) => {\n ruleRunner(rules[fnName], value, ...args);\n return proxy;\n };\n }\n });\n return proxy;\n };\n }\n\n // This is relatively heavier, and preferably should only be done when lacking proxy support\n return (value) => Object.keys(rulesObject).reduce((allRules, fnName) => {\n if (!isRule(rulesObject, fnName)) { return allRules; }\n\n allRules[fnName] = (...args) => {\n ruleRunner(rulesObject[fnName], value, ...args);\n return allRules;\n };\n\n return allRules;\n }, {});\n};\n\nexport default Enforce;","// @flow\n\n/**\n * Run tests and catch errors\n *\n * @param {function} callback The test content\n * @return {boolean}\n */\nfunction validate(test: PassableTest): boolean {\n\n if (typeof test !== 'function' && !(test instanceof Promise)) {\n throw new TypeError(`[Validate]: expected ${typeof test} to be a function.`);\n }\n\n try {\n return test() !== false;\n } catch (_) {\n return false;\n }\n}\n\nexport default validate;","// @flow\nimport Passable from './core/Passable';\nimport Enforce from './Enforce';\nimport validate from './validate';\nimport { WARN, FAIL } from './constants';\n\nfunction passable(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n const suite: Passable = new Passable(name, tests, specific);\n return suite.res.output;\n}\n\npassable.VERSION = PASSABLE_VERSION;\npassable.enforce = new Enforce({});\npassable.Enforce = Enforce;\npassable.validate = validate;\npassable.WARN = WARN;\npassable.FAIL = FAIL;\n\nexport default passable;"],"names":["WARN","FAIL","severities","passableResult","name","completionCallbacks","asyncObject","hasValidationErrors","hasValidationWarnings","cancelled","initFieldCounters","fieldName","output","testsPerformed","testCount","failCount","warnCount","bumpTestCounter","bumpTestWarning","statement","warnings","push","bumpTestError","errors","fail","severity","selectedSeverity","includes","addToSkipped","skipped","runCompletionCallbacks","forEach","cb","markAsync","done","callbacks","markAsDone","callback","after","cancel","getErrors","getWarnings","hasErrors","Boolean","length","hasWarnings","Specific","specific","is","TypeError","Array","isArray","only","populateGroup","not","group","field","item","every","hasOwnProperty","constructorError","value","doc","Passable","tests","test","pending","filter","t","some","excludes","res","operation","runTest","Promise","addPendingTest","isAsync","then","testResult","clearPendingTest","hasRemainingPendingTests","e","runPendingTests","negativeForm","isNumber","isString","matches","regex","RegExp","inside","arg1","equals","isNumeric","result","isNaN","parseFloat","Number","isFinite","isEmpty","Object","keys","greaterThan","alias","greaterThanOrEquals","lessThan","lessThanOrEquals","longerThan","longerThanOrEquals","shorterThan","shorterThanOrEquals","lengthEquals","extendRules","rules","rule","args","Error","glob","Function","isRule","rulesObject","Enforce","customRules","Proxy","proxy","get","fnName","ruleRunner","reduce","allRules","validate","_","passable","suite","VERSION","PASSABLE_VERSION","enforce"],"mappings":"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"} \ No newline at end of file diff --git a/dist/passable.min.js b/dist/passable.min.js index 7400ae87..0feff361 100644 --- a/dist/passable.min.js +++ b/dist/passable.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=n||self).passable=t()}(this,function(){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n})(t)}function t(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}function e(n,t){for(var e=0;eNumber(t)}function b(n,t){return g(n)&&g(t)&&Number(n)>=Number(t)}function v(n,t){return g(n)&&g(t)&&Number(n)t},longerThanOrEquals:function(n,t){return n.length>=t},shorterThan:function(n,t){return n.length2?r-2:0),i=2;i0&&void 0!==arguments[0]?arguments[0]:{},t=function(n){for(var t=1;tNumber(t)}function b(n,t){return h(n)&&h(t)&&Number(n)>=Number(t)}function v(n,t){return h(n)&&h(t)&&Number(n)t},longerThanOrEquals:function(n,t){return n.length>=t},shorterThan:function(n,t){return n.length2?r-2:0),o=2;o0&&void 0!==arguments[0]?arguments[0]:{},t=function(n){for(var t=1;t {\n\n const completionCallbacks: Function[] = [];\n let asyncObject: AsyncObject = null;\n let hasValidationErrors: boolean = false;\n let hasValidationWarnings: boolean = false;\n\n /**\n * Initializes specific field's counters\n * @param {string} fieldName - The name of the field.\n */\n const initFieldCounters: Function = (fieldName: string) => {\n if (output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName] = {\n testCount: 0,\n failCount: 0,\n warnCount: 0\n };\n };\n\n /**\n * Bumps test counters to indicate tests that's being performed\n * @param {string} fieldName - The name of the field.\n */\n const bumpTestCounter: Function = (fieldName: string) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName].testCount++;\n output.testCount++;\n };\n\n /**\n * Bumps field's warning counts and adds warning string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestWarning: Function = (fieldName: string, statement: string) => {\n hasValidationWarnings = true;\n output.warnings[fieldName] = output.warnings[fieldName] || [];\n output.warnings[fieldName].push(statement);\n output.warnCount++;\n output.testsPerformed[fieldName].warnCount++;\n };\n\n /**\n * Bumps field's error counts and adds error string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestError: Function = (fieldName: string, statement: string) => {\n hasValidationErrors = true;\n output.errors[fieldName] = output.errors[fieldName] || [];\n output.errors[fieldName].push(statement);\n output.failCount++;\n output.testsPerformed[fieldName].failCount++;\n };\n\n /**\n * Fails a field and updates output accordingly\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n * @param {string} severity - Whether it is a `fail` or `warn` test.\n */\n const fail: Function = (fieldName: string, statement: string, severity: Severity) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n const selectedSeverity: Severity = severity && severities.includes(severity) ? severity : FAIL;\n\n selectedSeverity === WARN\n ? bumpTestWarning(fieldName, statement)\n : bumpTestError(fieldName, statement);\n };\n\n /**\n * Uniquely add a field to the `skipped` list\n * @param {string} fieldName\n */\n const addToSkipped: Function = (fieldName: string) => {\n !output.skipped.includes(fieldName) && output.skipped.push(fieldName);\n };\n\n /**\n * Runs completion callbacks aggregated by `done`\n * regardless of success or failure\n */\n const runCompletionCallbacks: Function = () => {\n completionCallbacks.forEach((cb) => cb(output));\n };\n\n /**\n * Marks a field as async\n * @param {string} fieldName the name of the field marked as async\n */\n const markAsync: Function = (fieldName: string) => {\n asyncObject = asyncObject || {};\n asyncObject[fieldName] = asyncObject[fieldName] || {};\n asyncObject[fieldName] = {\n done: false,\n callbacks: asyncObject[fieldName].callbacks || []\n };\n };\n\n /**\n * Marks an async field as done\n * @param {string} fieldName the name of the field marked as done\n */\n const markAsDone: Function = (fieldName: string) => {\n if (asyncObject !== null && asyncObject[fieldName]) {\n asyncObject[fieldName].done = true;\n\n // run field callbacks set in `after`\n if (asyncObject[fieldName].callbacks) {\n asyncObject[fieldName].callbacks.forEach((callback) => callback(output));\n }\n\n runCompletionCallbacks();\n }\n };\n\n /**\n * Registers callback functions to be run when test suite is done running\n * If current suite is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const done: Function = (callback: Function) => {\n if (typeof callback !== 'function') {return output;}\n\n if (!asyncObject) {\n callback(output);\n }\n\n completionCallbacks.push(callback);\n return output;\n };\n\n /**\n * Registers callback functions to be run when a certain field is done running\n * If field is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const after: Function = (fieldName: string, callback) => {\n if (typeof callback !== 'function') {\n return output;\n }\n\n asyncObject = asyncObject || {};\n if (!asyncObject[fieldName] && output.testsPerformed[fieldName]) {\n callback(output);\n } else if (asyncObject[fieldName]) {\n asyncObject[fieldName].callbacks = [...(asyncObject[fieldName].callbacks || []), callback];\n }\n\n return output;\n };\n\n /**\n * Gets all the errors of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's errors, or all errors\n */\n const getErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.errors;\n }\n\n if (output.errors[fieldName]) {\n return output.errors[fieldName];\n }\n\n return [];\n };\n\n /**\n * Gets all the warnings of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's warnings, or all warnings\n */\n const getWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.warnings;\n }\n\n if (output.warnings[fieldName]) {\n return output.warnings[fieldName];\n }\n\n return [];\n };\n\n /**\n * Checks if a certain field (or the whole suite) has errors\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationErrors;\n }\n\n return Boolean(output.getErrors(fieldName).length);\n };\n\n /**\n * Checks if a certain field (or the whole suite) has warnings\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationWarnings;\n }\n\n return Boolean(output.getWarnings(fieldName).length);\n };\n\n const output: PassableOutput = {\n name,\n failCount: 0,\n warnCount: 0,\n testCount: 0,\n testsPerformed: {},\n errors: {},\n warnings: {},\n skipped: [],\n hasErrors,\n hasWarnings,\n getErrors,\n getWarnings,\n done,\n after\n };\n\n return {\n initFieldCounters,\n bumpTestError,\n bumpTestWarning,\n bumpTestCounter,\n fail,\n addToSkipped,\n runCompletionCallbacks,\n markAsync,\n markAsDone,\n output\n };\n};\n\nexport default passableResult;","// @flow\n\n/** Class representing validation inclusion and exclusion groups */\nclass Specific {\n not: SpecificGroup;\n only: SpecificGroup;\n\n /**\n * Initialize Specific object\n *\n * @param {String | Array | Object | undefined} specific\n */\n constructor(specific: ?SpecificArgs) {\n\n if (!specific) { return; }\n\n if (!Specific.is(specific)) {\n throw new TypeError();\n }\n\n if (typeof specific === 'string' || Array.isArray(specific)) {\n if (specific.length === 0) { return; }\n this.only = this.populateGroup(this.only, specific);\n return;\n }\n\n if (specific.only) {\n this.only = this.populateGroup(this.only, specific.only);\n }\n\n if (specific.not) {\n this.not = this.populateGroup(this.not, specific.not);\n }\n }\n\n /**\n * Populate inclusion and exclusion groups\n *\n * @param {Object} group - the group to populate.\n * @param {String | Array} field - the field to add to the group\n * @return {Object} modified group\n */\n populateGroup(group: SpecificGroup, field: SpecificField) {\n group = group || {};\n\n if (typeof field === 'string') {\n group[field] = true;\n } else if (Array.isArray(field)) {\n field.forEach((item) => group[item] = true);\n }\n\n return group;\n }\n\n /**\n * Checkes whether a given field name is in exclusion group\n * or not a member of inclusion group (when present)\n *\n * @param {String} fieldName\n * @return {Boolean}\n */\n excludes(fieldName: string) {\n if (this.only && !this.only[fieldName]) {\n return true;\n }\n\n if (this.not && this.not[fieldName]) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Test whether a given argument matches\n * the `specific` filter convention\n *\n * @param {Any} item\n * @return {boolean}\n */\n static is(item: AnyValue) {\n if (Array.isArray(item)) {\n return item.every((item) => typeof item === 'string');\n }\n\n if (typeof item === 'string') { return true; }\n\n if (item !== null && typeof item === 'object' && (\n item.hasOwnProperty('only')\n || item.hasOwnProperty('not')\n )) {\n return true;\n }\n\n return false;\n }\n}\n\nexport default Specific;","// @flow\n\nimport passableResult from '../passableResult';\nimport Specific from '../Specific';\n\nconst constructorError: Function = (name: string, value: string, doc?: string): string => `[Passable]: failed during suite initialization. Unexpected '${typeof value}' for '${name}' argument.\n See: ${doc ? doc : 'https://fiverr.github.io/passable/getting_started/writing_tests.html'}`;\n\n/**\n * Describes a passable validation suite\n */\nclass Passable {\n specific: Specific;\n res: PassableResult;\n test: TestProvider;\n pending: Array;\n\n pending = [];\n\n /**\n * Initializes a validation suite, creates a new passableResult instance and runs pending tests\n */\n constructor(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n\n if (typeof name !== 'string') {\n throw new TypeError(constructorError('suite name', name));\n }\n\n if (typeof tests !== 'function') {\n throw new TypeError(constructorError('tests', tests));\n }\n\n if (specific && !Specific.is(specific)) {\n throw new TypeError(constructorError('specific', tests, 'https://fiverr.github.io/passable/test/specific.html'));\n }\n\n this.specific = new Specific(specific);\n\n this.res = passableResult(name);\n\n tests(this.test, this.res.output);\n this.runPendingTests();\n }\n\n addPendingTest = (test: PassableTest) => this.pending.push(test);\n\n clearPendingTest = (test: PassableTest) => {\n this.pending = (this.pending.filter((t: PassableTest): boolean => t !== test): Array);\n };\n\n /**\n * Checks if a given field name still has pending tests\n * @param {String} fieldName name of the field to test against\n * @return {Boolean}\n */\n hasRemainingPendingTests = (fieldName: string) => this.pending.some((test) => test.fieldName === fieldName);\n\n /**\n * Test function passed over to the consumer.\n * It initiates field validation, and adds te test to the pending tests list\n * @param {string} fieldName the name of the field being validated\n * @param {string} statement description of the test\n * @param {function | Promise} test the actual test callback or promise\n */\n test = (fieldName: string, statement: string, test: PassableTest, severity: Severity) => {\n\n if (this.specific.excludes(fieldName)) {\n this.res.addToSkipped(fieldName);\n return;\n }\n\n this.res.initFieldCounters(fieldName);\n\n let operation: Function;\n\n if (typeof test === 'function') {\n operation = this.runTest;\n } else if (test instanceof Promise) {\n operation = this.addPendingTest;\n } else {\n return;\n }\n\n test.fieldName = fieldName;\n test.statement = statement;\n test.severity = severity;\n\n operation(test);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n * @param {function | Promise} test the actual test callback or promise\n */\n runTest = (test: PassableTest) => {\n\n const {\n fieldName,\n statement,\n severity\n }: {\n severity: Severity,\n fieldName: string,\n statement: string\n } = test;\n\n let isAsync: boolean = typeof test.then === 'function';\n let testResult: AnyValue;\n\n\n if (!isAsync) {\n try {\n testResult = test();\n } catch (e) {\n testResult = false;\n }\n\n if (testResult && typeof testResult.then === 'function') {\n isAsync = true;\n\n // $FlowFixMe\n test = testResult;\n }\n }\n\n if (isAsync) {\n this.res.markAsync(fieldName);\n\n const done: Function = () => {\n this.clearPendingTest(test);\n if (!this.hasRemainingPendingTests(fieldName)) {\n this.res.markAsDone(fieldName);\n }\n };\n\n const fail: Function = () => {\n // order is important here! fail needs to be called before `done`.\n this.res.fail(fieldName, statement, severity);\n done();\n };\n\n try {\n // $FlowFixMe\n test.then(done, fail);\n } catch (e) {\n fail();\n }\n } else {\n\n if (testResult === false) {\n this.res.fail(fieldName, statement, severity);\n }\n this.clearPendingTest(test);\n }\n this.res.bumpTestCounter(fieldName);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n */\n runPendingTests = () => {\n [...this.pending].forEach(this.runTest);\n }\n}\n\nexport default Passable;","// @flow\n\nfunction isArray(value: mixed): boolean {\n return Boolean(Array.isArray(value));\n}\n\nisArray.negativeForm = 'isNotArray';\n\nexport default isArray;","// @flow\n\nfunction isNumber(value: mixed): boolean {\n return Boolean(typeof value === 'number');\n}\n\nisNumber.negativeForm = 'isNotNumber';\n\nexport default isNumber;","// @flow\n\nfunction isString(value: mixed): boolean {\n return Boolean(typeof value === 'string');\n}\n\nisString.negativeForm = 'isNotString';\n\nexport default isString;","// @flow\n\nfunction matches(value: string, regex: RegExp | string): boolean {\n\n if (regex instanceof RegExp) {\n return regex.test(value);\n } else if (typeof regex === 'string') {\n return new RegExp(regex).test(value);\n } else {\n return false;\n }\n}\n\nmatches.negativeForm = 'notMatches';\n\nexport default matches;","// @flow\n\ntype All = NumStrBool | Array;\ntype Value = All | Array;\ntype Arg = string | Array;\n\nfunction inside(value: Value, arg1: Arg): boolean {\n\n if (Array.isArray(arg1) && ['string', 'number', 'boolean'].includes(typeof value)) {\n return arg1.includes(value);\n }\n\n // both value and arg1 are strings\n if (typeof arg1 === 'string' && typeof value === 'string') {\n return arg1.includes(value);\n }\n\n return false;\n}\n\ninside.negativeForm = 'notInside';\n\nexport default inside;","// @flow\n\nfunction equals(value: AnyValue, arg1: AnyValue): boolean {\n return value === arg1;\n}\n\nequals.negativeForm = 'notEquals';\n\nexport default equals;","// @flow\n\nfunction isNumeric(value: mixed): boolean {\n const result: boolean = !isNaN(parseFloat(value)) && !isNaN(Number(value)) && isFinite(value);\n return Boolean(result);\n}\n\nisNumeric.negativeForm = 'isNotNumeric';\n\nexport default isNumeric;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction isEmpty(value: AnyValue): boolean {\n if (!value) {\n return true;\n } else if (isNumeric(value)) {\n return value === 0;\n } else if (value.hasOwnProperty('length')) {\n return value.length === 0;\n } else if (typeof value === 'object') {\n return Object.keys(value).length === 0;\n } else {\n return true;\n }\n};\n\nisEmpty.negativeForm = 'isNotEmpty';\n\nexport default isEmpty;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) > Number(arg1);\n}\n\ngreaterThan.alias = 'gt';\n\nexport default greaterThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) >= Number(arg1);\n}\n\ngreaterThanOrEquals.alias = 'gte';\n\nexport default greaterThanOrEquals;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) < Number(arg1);\n}\n\nlessThan.alias = 'lt';\n\nexport default lessThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) <= Number(arg1);\n}\n\nlessThanOrEquals.alias = 'lte';\n\nexport default lessThanOrEquals;","// @flow\n\nfunction lengthEquals(value: StringOrArray, arg1: number): boolean {\n return value.length === arg1;\n}\n\nlengthEquals.negativeForm = 'lengthNotEquals';\n\nexport default lengthEquals;\n","// // @flow\n\nimport isArray from './rules/is_array';\nimport isNumber from './rules/is_number';\nimport isString from './rules/is_string';\nimport matches from './rules/matches';\nimport inside from './rules/inside';\nimport equals from './rules/equals';\nimport isNumeric from './rules/is_numeric';\nimport isEmpty from './rules/is_empty';\nimport greaterThan from './rules/greater_than';\nimport greaterThanOrEquals from './rules/greater_than_or_equals';\nimport lessThan from './rules/less_than';\nimport lessThanOrEquals from './rules/less_than_or_equals';\nimport longerThan from './rules/longer_than';\nimport longerThanOrEquals from './rules/longer_than_or_equals';\nimport shorterThan from './rules/shorter_than';\nimport shorterThanOrEquals from './rules/shorter_than_or_equals';\nimport lengthEquals from './rules/length_equals';\nimport extendRules from './helpers/extend_rules';\n\nconst rules: EnforceRules = {\n isArray,\n isNumber,\n isString,\n matches,\n inside,\n equals,\n isNumeric,\n isEmpty,\n greaterThan,\n greaterThanOrEquals,\n lessThan,\n lessThanOrEquals,\n longerThan,\n longerThanOrEquals,\n shorterThan,\n shorterThanOrEquals,\n lengthEquals\n};\n\nexport default extendRules(rules);","// @flow\n\n/**\n * Collects rules with `negativeForm` or `alias` attributes.\n * Adds a rule with the correct configuration.\n * @param {Object} rules - enforce rules object\n * @returns {Object} extended rules object\n */\nfunction extendRules(rules: EnforceRules) {\n\n for (const rule: string in rules) {\n const negativeForm: string = rules[rule].negativeForm;\n const alias: string = rules[rule].alias;\n\n if (negativeForm) {\n rules[negativeForm] = (...args) => !rules[rule](...args);\n }\n\n if (alias) {\n rules[alias] = rules[rule];\n }\n }\n\n return rules;\n}\n\nexport default extendRules;\n","// @flow\n\nfunction longerThan(value: StringOrArray, arg1: number): boolean {\n return value.length > arg1;\n}\n\nexport default longerThan;\n","// @flow\n\nfunction longerThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length >= arg1;\n}\n\nexport default longerThanOrEquals;\n","// @flow\n\nfunction shorterThan(value: StringOrArray, arg1: number): boolean {\n return value.length < arg1;\n}\n\nexport default shorterThan;\n","// @flow\n\nfunction shorterThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length <= arg1;\n}\n\nexport default shorterThanOrEquals;\n","// @flow\n\n/**\n * Run a single rule against enforced value (e.g. `isNumber()`)\n *\n * @param {Function} rule - rule to run\n * @param {Any} value\n * @param {Array} args list of arguments sent from consumer\n */\nfunction rule(rule: EnforceRule, value: AnyValue, ...args: RuleArgs): void {\n\n if (typeof rule !== 'function') { return; }\n\n if (rule(value, ...args) !== true) {\n throw new Error(`[Enforce]: invalid ${typeof value} value`);\n }\n}\n\nexport default rule;\n","// @flow\n\nimport rules from './runnables';\nimport ruleRunner from './runners/rule';\n\n// $FlowFixMe\nconst glob: GlobalObject = Function('return this')();\n\nconst isRule: Function = (rulesObject, name): boolean => (\n rulesObject.hasOwnProperty(name) && typeof rulesObject[name] === 'function'\n);\n\nconst Enforce: Function = (customRules: EnforceRules = {}): EnforceInstance => {\n const rulesObject: EnforceRules = {...rules, ...customRules};\n\n if (typeof Proxy === 'function') {\n return (value: AnyValue): EnforceRules => {\n const proxy: EnforceRules = new Proxy(rulesObject, {\n get: (rules, fnName) => {\n if (!isRule(rules, fnName)) { return; }\n\n return (...args) => {\n ruleRunner(rules[fnName], value, ...args);\n return proxy;\n };\n }\n });\n return proxy;\n };\n }\n\n // This is relatively heavier, and preferably should only be done when lacking proxy support\n return (value) => Object.keys(rulesObject).reduce((allRules, fnName) => {\n if (!isRule(rulesObject, fnName)) { return allRules; }\n\n allRules[fnName] = (...args) => {\n ruleRunner(rulesObject[fnName], value, ...args);\n return allRules;\n };\n\n return allRules;\n }, {});\n};\n\nexport default Enforce;","// @flow\nimport Passable from './core/Passable';\nimport Enforce from './Enforce';\nimport validate from './validate';\nimport { WARN, FAIL } from './constants';\n\nfunction passable(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n const suite: Passable = new Passable(name, tests, specific);\n return suite.res.output;\n}\n\npassable.VERSION = PASSABLE_VERSION;\npassable.enforce = new Enforce({});\npassable.Enforce = Enforce;\npassable.validate = validate;\npassable.WARN = WARN;\npassable.FAIL = FAIL;\n\nexport default passable;","// @flow\n\n/**\n * Run tests and catch errors\n *\n * @param {function} callback The test content\n * @return {boolean}\n */\nfunction validate(test: PassableTest): boolean {\n\n if (typeof test !== 'function' && !(test instanceof Promise)) {\n throw new TypeError(`[Validate]: expected ${typeof test} to be a function.`);\n }\n\n try {\n return test() !== false;\n } catch (_) {\n return false;\n }\n}\n\nexport default validate;"],"names":["severities","Specific","specific","is","TypeError","Array","isArray","length","only","this","populateGroup","not","item","every","_typeof","hasOwnProperty","group","field","forEach","fieldName","constructorError","name","value","doc","Passable","tests","test","_this","pending","push","filter","t","some","statement","severity","excludes","res","addToSkipped","operation","initFieldCounters","runTest","Promise","addPendingTest","testResult","isAsync","then","e","markAsync","done","clearPendingTest","hasRemainingPendingTests","markAsDone","fail","bumpTestCounter","completionCallbacks","asyncObject","hasValidationErrors","hasValidationWarnings","bumpTestWarning","output","warnings","warnCount","testsPerformed","bumpTestError","errors","failCount","runCompletionCallbacks","cb","testCount","skipped","hasErrors","Boolean","getErrors","hasWarnings","getWarnings","callback","after","callbacks","includes","passableResult","runPendingTests","isNumber","isString","matches","regex","RegExp","inside","arg1","equals","isNumeric","result","isNaN","parseFloat","Number","isFinite","isEmpty","Object","keys","greaterThan","greaterThanOrEquals","lessThan","lessThanOrEquals","lengthEquals","negativeForm","alias","rules","rule","extendRules","longerThan","longerThanOrEquals","shorterThan","shorterThanOrEquals","args","Error","Function","isRule","rulesObject","Enforce","customRules","Proxy","proxy","get","fnName","ruleRunner","reduce","allRules","passable","VERSION","PASSABLE_VERSION","enforce","validate","_","WARN","FAIL"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"passable.min.js","sources":["../src/constants.js","../src/core/passableResult/index.js","../src/core/Specific/index.js","../src/core/Passable/index.js","../src/Enforce/runnables/rules/is_array/index.js","../src/Enforce/runnables/rules/is_number/index.js","../src/Enforce/runnables/rules/is_string/index.js","../src/Enforce/runnables/rules/matches/index.js","../src/Enforce/runnables/rules/inside/index.js","../src/Enforce/runnables/rules/equals/index.js","../src/Enforce/runnables/rules/is_numeric/index.js","../src/Enforce/runnables/rules/is_empty/index.js","../src/Enforce/runnables/rules/greater_than/index.js","../src/Enforce/runnables/rules/greater_than_or_equals/index.js","../src/Enforce/runnables/rules/less_than/index.js","../src/Enforce/runnables/rules/less_than_or_equals/index.js","../src/Enforce/runnables/rules/length_equals/index.js","../src/Enforce/runnables/index.js","../src/Enforce/runnables/helpers/extend_rules/index.js","../src/Enforce/runnables/rules/longer_than/index.js","../src/Enforce/runnables/rules/longer_than_or_equals/index.js","../src/Enforce/runnables/rules/shorter_than/index.js","../src/Enforce/runnables/rules/shorter_than_or_equals/index.js","../src/Enforce/runners/rule/index.js","../src/Enforce/index.js","../src/index.js","../src/validate/index.js"],"sourcesContent":["// @flow\n\nexport const WARN: Severity = 'warn';\nexport const FAIL: Severity = 'fail';","// @flow\n\nimport { WARN, FAIL } from '../../constants';\nconst severities: string[] = [ WARN, FAIL ];\n\ntype AsyncObject = null | {\n [fieldName: string]: {\n done: boolean,\n callbacks: Function[]\n }\n};\n\nconst passableResult: Function = (name: string): PassableResult => {\n\n const completionCallbacks: Function[] = [];\n let asyncObject: AsyncObject = null;\n let hasValidationErrors: boolean = false;\n let hasValidationWarnings: boolean = false;\n let cancelled: boolean = false;\n\n /**\n * Initializes specific field's counters\n * @param {string} fieldName - The name of the field.\n */\n const initFieldCounters: Function = (fieldName: string) => {\n if (output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName] = {\n testCount: 0,\n failCount: 0,\n warnCount: 0\n };\n };\n\n /**\n * Bumps test counters to indicate tests that's being performed\n * @param {string} fieldName - The name of the field.\n */\n const bumpTestCounter: Function = (fieldName: string) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n output.testsPerformed[fieldName].testCount++;\n output.testCount++;\n };\n\n /**\n * Bumps field's warning counts and adds warning string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestWarning: Function = (fieldName: string, statement: string) => {\n hasValidationWarnings = true;\n output.warnings[fieldName] = output.warnings[fieldName] || [];\n output.warnings[fieldName].push(statement);\n output.warnCount++;\n output.testsPerformed[fieldName].warnCount++;\n };\n\n /**\n * Bumps field's error counts and adds error string\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n */\n const bumpTestError: Function = (fieldName: string, statement: string) => {\n hasValidationErrors = true;\n output.errors[fieldName] = output.errors[fieldName] || [];\n output.errors[fieldName].push(statement);\n output.failCount++;\n output.testsPerformed[fieldName].failCount++;\n };\n\n /**\n * Fails a field and updates output accordingly\n * @param {string} fieldName - The name of the field.\n * @param {string} statement - The error string to add to the object.\n * @param {string} severity - Whether it is a `fail` or `warn` test.\n */\n const fail: Function = (fieldName: string, statement: string, severity: Severity) => {\n if (!output.testsPerformed[fieldName]) { return output; }\n\n const selectedSeverity: Severity = severity && severities.includes(severity) ? severity : FAIL;\n\n selectedSeverity === WARN\n ? bumpTestWarning(fieldName, statement)\n : bumpTestError(fieldName, statement);\n };\n\n /**\n * Uniquely add a field to the `skipped` list\n * @param {string} fieldName\n */\n const addToSkipped: Function = (fieldName: string) => {\n !output.skipped.includes(fieldName) && output.skipped.push(fieldName);\n };\n\n /**\n * Runs completion callbacks aggregated by `done`\n * regardless of success or failure\n */\n const runCompletionCallbacks: Function = () => {\n completionCallbacks.forEach((cb) => !cancelled && cb(output));\n };\n\n /**\n * Marks a field as async\n * @param {string} fieldName the name of the field marked as async\n */\n const markAsync: Function = (fieldName: string) => {\n asyncObject = asyncObject || {};\n asyncObject[fieldName] = asyncObject[fieldName] || {};\n asyncObject[fieldName] = {\n done: false,\n callbacks: asyncObject[fieldName].callbacks || []\n };\n };\n\n /**\n * Marks an async field as done\n * @param {string} fieldName the name of the field marked as done\n */\n const markAsDone: Function = (fieldName?: string) => {\n\n if (!fieldName) {\n return runCompletionCallbacks();\n }\n\n if (asyncObject !== null && asyncObject[fieldName]) {\n asyncObject[fieldName].done = true;\n\n // run field callbacks set in `after`\n if (asyncObject[fieldName].callbacks) {\n asyncObject[fieldName].callbacks.forEach((callback) => !cancelled && callback(output));\n }\n }\n };\n\n /**\n * Registers callback functions to be run when test suite is done running\n * If current suite is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const done: Function = (callback: Function) => {\n if (typeof callback !== 'function') {return output;}\n\n if (!asyncObject) {\n callback(output);\n }\n\n completionCallbacks.push(callback);\n return output;\n };\n\n /**\n * Registers callback functions to be run when a certain field is done running\n * If field is not async, runs the callback immediately\n * @param {function} callback the function to be called on done\n * @return {object} output object\n */\n const after: Function = (fieldName: string, callback) => {\n if (typeof callback !== 'function') {\n return output;\n }\n\n asyncObject = asyncObject || {};\n if (!asyncObject[fieldName] && output.testsPerformed[fieldName]) {\n callback(output);\n } else if (asyncObject[fieldName]) {\n asyncObject[fieldName].callbacks = [...(asyncObject[fieldName].callbacks || []), callback];\n }\n\n return output;\n };\n\n /**\n * cancels done/after callbacks. They won't invoke when async operations complete\n */\n const cancel: Function = () => {\n cancelled = true;\n\n return output;\n };\n\n /**\n * Gets all the errors of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's errors, or all errors\n */\n const getErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.errors;\n }\n\n if (output.errors[fieldName]) {\n return output.errors[fieldName];\n }\n\n return [];\n };\n\n /**\n * Gets all the warnings of a field, or of the whole object\n * @param {string} [fieldName] - The name of the field.\n * @return {Array | Object} The field's warnings, or all warnings\n */\n const getWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return output.warnings;\n }\n\n if (output.warnings[fieldName]) {\n return output.warnings[fieldName];\n }\n\n return [];\n };\n\n /**\n * Checks if a certain field (or the whole suite) has errors\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasErrors: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationErrors;\n }\n\n return Boolean(output.getErrors(fieldName).length);\n };\n\n /**\n * Checks if a certain field (or the whole suite) has warnings\n * @param {string} [fieldName]\n * @return {boolean}\n */\n const hasWarnings: Function = (fieldName: string) => {\n if (!fieldName) {\n return hasValidationWarnings;\n }\n\n return Boolean(output.getWarnings(fieldName).length);\n };\n\n const output: PassableOutput = {\n name,\n failCount: 0,\n warnCount: 0,\n testCount: 0,\n testsPerformed: {},\n errors: {},\n warnings: {},\n skipped: [],\n hasErrors,\n hasWarnings,\n getErrors,\n getWarnings,\n done,\n after,\n cancel\n };\n\n return {\n initFieldCounters,\n bumpTestError,\n bumpTestWarning,\n bumpTestCounter,\n fail,\n addToSkipped,\n runCompletionCallbacks,\n markAsync,\n markAsDone,\n output\n };\n};\n\nexport default passableResult;","// @flow\n\n/** Class representing validation inclusion and exclusion groups */\nclass Specific {\n not: SpecificGroup;\n only: SpecificGroup;\n\n /**\n * Initialize Specific object\n *\n * @param {String | Array | Object | undefined} specific\n */\n constructor(specific: ?SpecificArgs) {\n\n if (!specific) { return; }\n\n if (!Specific.is(specific)) {\n throw new TypeError();\n }\n\n if (typeof specific === 'string' || Array.isArray(specific)) {\n if (specific.length === 0) { return; }\n this.only = this.populateGroup(this.only, specific);\n return;\n }\n\n if (specific.only) {\n this.only = this.populateGroup(this.only, specific.only);\n }\n\n if (specific.not) {\n this.not = this.populateGroup(this.not, specific.not);\n }\n }\n\n /**\n * Populate inclusion and exclusion groups\n *\n * @param {Object} group - the group to populate.\n * @param {String | Array} field - the field to add to the group\n * @return {Object} modified group\n */\n populateGroup(group: SpecificGroup, field: SpecificField) {\n group = group || {};\n\n if (typeof field === 'string') {\n group[field] = true;\n } else if (Array.isArray(field)) {\n field.forEach((item) => group[item] = true);\n }\n\n return group;\n }\n\n /**\n * Checkes whether a given field name is in exclusion group\n * or not a member of inclusion group (when present)\n *\n * @param {String} fieldName\n * @return {Boolean}\n */\n excludes(fieldName: string) {\n if (this.only && !this.only[fieldName]) {\n return true;\n }\n\n if (this.not && this.not[fieldName]) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Test whether a given argument matches\n * the `specific` filter convention\n *\n * @param {Any} item\n * @return {boolean}\n */\n static is(item: AnyValue) {\n if (Array.isArray(item)) {\n return item.every((item) => typeof item === 'string');\n }\n\n if (typeof item === 'string') { return true; }\n\n if (item !== null && typeof item === 'object' && (\n item.hasOwnProperty('only')\n || item.hasOwnProperty('not')\n )) {\n return true;\n }\n\n return false;\n }\n}\n\nexport default Specific;","// @flow\n\nimport passableResult from '../passableResult';\nimport Specific from '../Specific';\n\nconst constructorError: Function = (name: string, value: string, doc?: string): string => `[Passable]: failed during suite initialization. Unexpected '${typeof value}' for '${name}' argument.\n See: ${doc ? doc : 'https://fiverr.github.io/passable/getting_started/writing_tests.html'}`;\n\n/**\n * Describes a passable validation suite\n */\nclass Passable {\n specific: Specific;\n res: PassableResult;\n test: TestProvider;\n pending: Array = [];\n\n /**\n * Initializes a validation suite, creates a new passableResult instance and runs pending tests\n */\n constructor(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n\n if (typeof name !== 'string') {\n throw new TypeError(constructorError('suite name', name));\n }\n\n if (typeof tests !== 'function') {\n throw new TypeError(constructorError('tests', tests));\n }\n\n if (specific && !Specific.is(specific)) {\n throw new TypeError(constructorError('specific', tests, 'https://fiverr.github.io/passable/test/specific.html'));\n }\n\n this.specific = new Specific(specific);\n\n this.res = passableResult(name);\n\n tests(this.test, this.res.output);\n this.runPendingTests();\n }\n\n addPendingTest = (test: PassableTest) => this.pending.push(test);\n\n clearPendingTest = (test: PassableTest) => {\n this.pending = (this.pending.filter((t: PassableTest): boolean => t !== test): Array);\n };\n\n /**\n * Checks if a given field name still has pending tests\n * @param {String} fieldName name of the field to test against\n * @return {Boolean}\n */\n hasRemainingPendingTests = (fieldName?: string) => {\n if (!this.pending.length) {\n return false;\n }\n\n if (fieldName) {\n return this.pending.some((test) => test.fieldName === fieldName);\n }\n\n return !!this.pending.length;\n }\n\n /**\n * Test function passed over to the consumer.\n * It initiates field validation, and adds te test to the pending tests list\n * @param {string} fieldName the name of the field being validated\n * @param {string} statement description of the test\n * @param {function | Promise} test the actual test callback or promise\n */\n test = (fieldName: string, statement: string, test: PassableTest, severity: Severity) => {\n\n if (this.specific.excludes(fieldName)) {\n this.res.addToSkipped(fieldName);\n return;\n }\n\n this.res.initFieldCounters(fieldName);\n\n let operation: Function;\n\n if (typeof test === 'function') {\n operation = this.runTest;\n } else if (test instanceof Promise) {\n operation = this.addPendingTest;\n } else {\n return;\n }\n\n test.fieldName = fieldName;\n test.statement = statement;\n test.severity = severity;\n\n operation(test);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n * @param {function | Promise} test the actual test callback or promise\n */\n runTest = (test: PassableTest) => {\n\n const {\n fieldName,\n statement,\n severity\n }: {\n severity: Severity,\n fieldName: string,\n statement: string\n } = test;\n\n const isAsync: boolean = typeof test.then === 'function';\n let testResult: AnyValue;\n\n if (isAsync) {\n this.res.markAsync(fieldName);\n\n const done: Function = () => {\n this.clearPendingTest(test);\n if (!this.hasRemainingPendingTests(fieldName)) {\n this.res.markAsDone(fieldName);\n }\n\n if (!this.hasRemainingPendingTests()) {\n this.res.markAsDone();\n }\n };\n\n const fail: Function = () => {\n // order is important here! fail needs to be called before `done`.\n\n if (this.pending.includes(test)) {\n this.res.fail(fieldName, statement, severity);\n }\n done();\n };\n\n try {\n // $FlowFixMe\n test.then(done, fail);\n } catch (e) {\n fail(test);\n }\n } else {\n try {\n testResult = test();\n } catch (e) {\n testResult = false;\n }\n\n // if is async after all\n if (testResult && typeof testResult.then === 'function') {\n\n testResult.fieldName = fieldName;\n testResult.statement = statement;\n testResult.severity = severity;\n\n // $FlowFixMe\n return this.addPendingTest(testResult);\n }\n\n // explicitly false\n if (testResult === false) {\n this.res.fail(fieldName, statement, severity);\n }\n\n this.clearPendingTest(test);\n }\n\n this.res.bumpTestCounter(fieldName);\n }\n\n /**\n * calls `runTest` on all pending tests, clears pending tests list and bumps counters\n */\n runPendingTests = () => {\n [...this.pending].forEach(this.runTest);\n }\n}\n\nexport default Passable;","// @flow\n\nfunction isArray(value: mixed): boolean {\n return Boolean(Array.isArray(value));\n}\n\nisArray.negativeForm = 'isNotArray';\n\nexport default isArray;","// @flow\n\nfunction isNumber(value: mixed): boolean {\n return Boolean(typeof value === 'number');\n}\n\nisNumber.negativeForm = 'isNotNumber';\n\nexport default isNumber;","// @flow\n\nfunction isString(value: mixed): boolean {\n return Boolean(typeof value === 'string');\n}\n\nisString.negativeForm = 'isNotString';\n\nexport default isString;","// @flow\n\nfunction matches(value: string, regex: RegExp | string): boolean {\n\n if (regex instanceof RegExp) {\n return regex.test(value);\n } else if (typeof regex === 'string') {\n return new RegExp(regex).test(value);\n } else {\n return false;\n }\n}\n\nmatches.negativeForm = 'notMatches';\n\nexport default matches;","// @flow\n\ntype All = NumStrBool | Array;\ntype Value = All | Array;\ntype Arg = string | Array;\n\nfunction inside(value: Value, arg1: Arg): boolean {\n\n if (Array.isArray(arg1) && ['string', 'number', 'boolean'].includes(typeof value)) {\n return arg1.includes(value);\n }\n\n // both value and arg1 are strings\n if (typeof arg1 === 'string' && typeof value === 'string') {\n return arg1.includes(value);\n }\n\n return false;\n}\n\ninside.negativeForm = 'notInside';\n\nexport default inside;","// @flow\n\nfunction equals(value: AnyValue, arg1: AnyValue): boolean {\n return value === arg1;\n}\n\nequals.negativeForm = 'notEquals';\n\nexport default equals;","// @flow\n\nfunction isNumeric(value: mixed): boolean {\n const result: boolean = !isNaN(parseFloat(value)) && !isNaN(Number(value)) && isFinite(value);\n return Boolean(result);\n}\n\nisNumeric.negativeForm = 'isNotNumeric';\n\nexport default isNumeric;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction isEmpty(value: AnyValue): boolean {\n if (!value) {\n return true;\n } else if (isNumeric(value)) {\n return value === 0;\n } else if (value.hasOwnProperty('length')) {\n return value.length === 0;\n } else if (typeof value === 'object') {\n return Object.keys(value).length === 0;\n } else {\n return true;\n }\n};\n\nisEmpty.negativeForm = 'isNotEmpty';\n\nexport default isEmpty;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) > Number(arg1);\n}\n\ngreaterThan.alias = 'gt';\n\nexport default greaterThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction greaterThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) >= Number(arg1);\n}\n\ngreaterThanOrEquals.alias = 'gte';\n\nexport default greaterThanOrEquals;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThan(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) < Number(arg1);\n}\n\nlessThan.alias = 'lt';\n\nexport default lessThan;","// @flow\nimport isNumeric from '../is_numeric';\n\nfunction lessThanOrEquals(value: NumericValue, arg1: NumericValue): boolean {\n return isNumeric(value) && isNumeric(arg1) && Number(value) <= Number(arg1);\n}\n\nlessThanOrEquals.alias = 'lte';\n\nexport default lessThanOrEquals;","// @flow\n\nfunction lengthEquals(value: StringOrArray, arg1: number): boolean {\n return value.length === arg1;\n}\n\nlengthEquals.negativeForm = 'lengthNotEquals';\n\nexport default lengthEquals;\n","// // @flow\n\nimport isArray from './rules/is_array';\nimport isNumber from './rules/is_number';\nimport isString from './rules/is_string';\nimport matches from './rules/matches';\nimport inside from './rules/inside';\nimport equals from './rules/equals';\nimport isNumeric from './rules/is_numeric';\nimport isEmpty from './rules/is_empty';\nimport greaterThan from './rules/greater_than';\nimport greaterThanOrEquals from './rules/greater_than_or_equals';\nimport lessThan from './rules/less_than';\nimport lessThanOrEquals from './rules/less_than_or_equals';\nimport longerThan from './rules/longer_than';\nimport longerThanOrEquals from './rules/longer_than_or_equals';\nimport shorterThan from './rules/shorter_than';\nimport shorterThanOrEquals from './rules/shorter_than_or_equals';\nimport lengthEquals from './rules/length_equals';\nimport extendRules from './helpers/extend_rules';\n\nconst rules: EnforceRules = {\n isArray,\n isNumber,\n isString,\n matches,\n inside,\n equals,\n isNumeric,\n isEmpty,\n greaterThan,\n greaterThanOrEquals,\n lessThan,\n lessThanOrEquals,\n longerThan,\n longerThanOrEquals,\n shorterThan,\n shorterThanOrEquals,\n lengthEquals\n};\n\nexport default extendRules(rules);","// @flow\n\n/**\n * Collects rules with `negativeForm` or `alias` attributes.\n * Adds a rule with the correct configuration.\n * @param {Object} rules - enforce rules object\n * @returns {Object} extended rules object\n */\nfunction extendRules(rules: EnforceRules) {\n\n for (const rule: string in rules) {\n const negativeForm: string = rules[rule].negativeForm;\n const alias: string = rules[rule].alias;\n\n if (negativeForm) {\n rules[negativeForm] = (...args) => !rules[rule](...args);\n }\n\n if (alias) {\n rules[alias] = rules[rule];\n }\n }\n\n return rules;\n}\n\nexport default extendRules;\n","// @flow\n\nfunction longerThan(value: StringOrArray, arg1: number): boolean {\n return value.length > arg1;\n}\n\nexport default longerThan;\n","// @flow\n\nfunction longerThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length >= arg1;\n}\n\nexport default longerThanOrEquals;\n","// @flow\n\nfunction shorterThan(value: StringOrArray, arg1: number): boolean {\n return value.length < arg1;\n}\n\nexport default shorterThan;\n","// @flow\n\nfunction shorterThanOrEquals(value: StringOrArray, arg1: number): boolean {\n return value.length <= arg1;\n}\n\nexport default shorterThanOrEquals;\n","// @flow\n\n/**\n * Run a single rule against enforced value (e.g. `isNumber()`)\n *\n * @param {Function} rule - rule to run\n * @param {Any} value\n * @param {Array} args list of arguments sent from consumer\n */\nfunction rule(rule: EnforceRule, value: AnyValue, ...args: RuleArgs): void {\n\n if (typeof rule !== 'function') { return; }\n\n if (rule(value, ...args) !== true) {\n throw new Error(`[Enforce]: invalid ${typeof value} value`);\n }\n}\n\nexport default rule;\n","// @flow\n\nimport rules from './runnables';\nimport ruleRunner from './runners/rule';\n\n// $FlowFixMe\nconst glob: GlobalObject = Function('return this')();\n\nconst isRule: Function = (rulesObject, name): boolean => (\n rulesObject.hasOwnProperty(name) && typeof rulesObject[name] === 'function'\n);\n\nconst Enforce: Function = (customRules: EnforceRules = {}): EnforceInstance => {\n const rulesObject: EnforceRules = {...rules, ...customRules};\n\n if (typeof Proxy === 'function') {\n return (value: AnyValue): EnforceRules => {\n const proxy: EnforceRules = new Proxy(rulesObject, {\n get: (rules, fnName) => {\n if (!isRule(rules, fnName)) { return; }\n\n return (...args) => {\n ruleRunner(rules[fnName], value, ...args);\n return proxy;\n };\n }\n });\n return proxy;\n };\n }\n\n // This is relatively heavier, and preferably should only be done when lacking proxy support\n return (value) => Object.keys(rulesObject).reduce((allRules, fnName) => {\n if (!isRule(rulesObject, fnName)) { return allRules; }\n\n allRules[fnName] = (...args) => {\n ruleRunner(rulesObject[fnName], value, ...args);\n return allRules;\n };\n\n return allRules;\n }, {});\n};\n\nexport default Enforce;","// @flow\nimport Passable from './core/Passable';\nimport Enforce from './Enforce';\nimport validate from './validate';\nimport { WARN, FAIL } from './constants';\n\nfunction passable(name: string, tests: TestsWrapper, specific: ?SpecificArgs) {\n const suite: Passable = new Passable(name, tests, specific);\n return suite.res.output;\n}\n\npassable.VERSION = PASSABLE_VERSION;\npassable.enforce = new Enforce({});\npassable.Enforce = Enforce;\npassable.validate = validate;\npassable.WARN = WARN;\npassable.FAIL = FAIL;\n\nexport default passable;","// @flow\n\n/**\n * Run tests and catch errors\n *\n * @param {function} callback The test content\n * @return {boolean}\n */\nfunction validate(test: PassableTest): boolean {\n\n if (typeof test !== 'function' && !(test instanceof Promise)) {\n throw new TypeError(`[Validate]: expected ${typeof test} to be a function.`);\n }\n\n try {\n return test() !== false;\n } catch (_) {\n return false;\n }\n}\n\nexport default validate;"],"names":["severities","Specific","specific","is","TypeError","Array","isArray","length","only","this","populateGroup","not","item","every","_typeof","hasOwnProperty","group","field","forEach","fieldName","constructorError","name","value","doc","Passable","tests","test","_this","pending","push","filter","t","some","statement","severity","excludes","res","addToSkipped","operation","initFieldCounters","runTest","Promise","addPendingTest","testResult","then","markAsync","done","clearPendingTest","hasRemainingPendingTests","markAsDone","fail","includes","e","bumpTestCounter","completionCallbacks","asyncObject","hasValidationErrors","hasValidationWarnings","cancelled","bumpTestWarning","output","warnings","warnCount","testsPerformed","bumpTestError","errors","failCount","runCompletionCallbacks","cb","testCount","skipped","hasErrors","Boolean","getErrors","hasWarnings","getWarnings","callback","after","callbacks","cancel","passableResult","runPendingTests","isNumber","isString","matches","regex","RegExp","inside","arg1","equals","isNumeric","result","isNaN","parseFloat","Number","isFinite","isEmpty","Object","keys","greaterThan","greaterThanOrEquals","lessThan","lessThanOrEquals","lengthEquals","negativeForm","alias","rules","rule","extendRules","longerThan","longerThanOrEquals","shorterThan","shorterThanOrEquals","args","Error","Function","isRule","rulesObject","Enforce","customRules","Proxy","proxy","get","fnName","ruleRunner","reduce","allRules","passable","VERSION","PASSABLE_VERSION","enforce","validate","_","WARN","FAIL"],"mappings":"onCAEO,ICCDA,EAAuB,CDDC,OACA,QEAxBC,wBASUC,gBAEHA,OAEAD,EAASE,GAAGD,SACP,IAAIE,aAGU,iBAAbF,GAAyBG,MAAMC,QAAQJ,OACtB,IAApBA,EAASK,mBACRC,KAAOC,KAAKC,cAAcD,KAAKD,KAAMN,QAI1CA,EAASM,YACJA,KAAOC,KAAKC,cAAcD,KAAKD,KAAMN,EAASM,OAGnDN,EAASS,WACJA,IAAMF,KAAKC,cAAcD,KAAKE,IAAKT,EAASS,wDAiD/CC,UACFP,MAAMC,QAAQM,GACPA,EAAKC,MAAM,SAACD,SAAyB,iBAATA,IAGnB,iBAATA,KAEE,OAATA,GAAiC,WAAhBE,EAAOF,KACxBA,EAAKG,eAAe,UACjBH,EAAKG,eAAe,mDA/CjBC,EAAsBC,UAChCD,EAAQA,GAAS,GAEI,iBAAVC,EACPD,EAAMC,IAAS,EACRZ,MAAMC,QAAQW,IACrBA,EAAMC,QAAQ,SAACN,UAASI,EAAMJ,IAAQ,IAGnCI,mCAUFG,YACDV,KAAKD,MAASC,KAAKD,KAAKW,QAIxBV,KAAKE,MAAOF,KAAKE,IAAIQ,yCC7D3BC,EAA6B,SAACC,EAAcC,EAAeC,iFAA+FD,qBAAeD,mCACpKE,GAAY,yEAKjBC,EASF,WAAYH,EAAcI,EAAqBvB,4CALhB,4BA2Bd,SAACwB,UAAuBC,EAAKC,QAAQC,KAAKH,+BAExC,SAACA,GAChBC,EAAKC,QAAWD,EAAKC,QAAQE,OAAO,SAACC,UAA6BA,IAAML,wCAQjD,SAACP,WACnBQ,EAAKC,QAAQrB,SAIdY,EACOQ,EAAKC,QAAQI,KAAK,SAACN,UAASA,EAAKP,YAAcA,MAGjDQ,EAAKC,QAAQrB,wBAUnB,SAACY,EAAmBc,EAAmBP,EAAoBQ,MAE1DP,EAAKzB,SAASiC,SAAShB,GACvBQ,EAAKS,IAAIC,aAAalB,YAMtBmB,KAFJX,EAAKS,IAAIG,kBAAkBpB,GAIP,mBAATO,EACPY,EAAYX,EAAKa,YACd,CAAA,KAAId,aAAgBe,gBACvBH,EAAYX,EAAKe,eAKrBhB,EAAKP,UAAYA,EACjBO,EAAKO,UAAYA,EACjBP,EAAKQ,SAAWA,EAEhBI,EAAUZ,uBAOJ,SAACA,OAaHiB,EAVAxB,EAOAO,EAPAP,UACAc,EAMAP,EANAO,UACAC,EAKAR,EALAQ,YAO0C,mBAAdR,EAAKkB,KAGxB,CACTjB,EAAKS,IAAIS,UAAU1B,OAEb2B,EAAiB,WACnBnB,EAAKoB,iBAAiBrB,GACjBC,EAAKqB,yBAAyB7B,IAC/BQ,EAAKS,IAAIa,WAAW9B,GAGnBQ,EAAKqB,4BACNrB,EAAKS,IAAIa,cAIXC,EAAiB,WAGfvB,EAAKC,QAAQuB,SAASzB,IACtBC,EAAKS,IAAIc,KAAK/B,EAAWc,EAAWC,GAExCY,SAKApB,EAAKkB,KAAKE,EAAMI,GAClB,MAAOE,GACLF,SAED,KAECP,EAAajB,IACf,MAAO0B,GACLT,GAAa,KAIbA,GAAyC,mBAApBA,EAAWC,YAEhCD,EAAWxB,UAAYA,EACvBwB,EAAWV,UAAYA,EACvBU,EAAWT,SAAWA,EAGfP,EAAKe,eAAeC,IAIZ,IAAfA,GACAhB,EAAKS,IAAIc,KAAK/B,EAAWc,EAAWC,GAGxCP,EAAKoB,iBAAiBrB,GAG1BC,EAAKS,IAAIiB,gBAAgBlC,8BAMX,aACVQ,EAAKC,SAASV,QAAQS,EAAKa,WA7JX,iBAATnB,QACD,IAAIjB,UAAUgB,EAAiB,aAAcC,OAGlC,mBAAVI,QACD,IAAIrB,UAAUgB,EAAiB,QAASK,OAG9CvB,IAAaD,EAASE,GAAGD,SACnB,IAAIE,UAAUgB,EAAiB,WAAYK,EAAO,8DAGvDvB,SAAW,IAAID,EAASC,QAExBkC,IFxBoB,SAACf,OAExBiC,EAAkC,GACpCC,EAA2B,KAC3BC,GAA+B,EAC/BC,GAAiC,EACjCC,GAAqB,EAgCnBC,EAA4B,SAACxC,EAAmBc,GAClDwB,GAAwB,EACxBG,EAAOC,SAAS1C,GAAayC,EAAOC,SAAS1C,IAAc,GAC3DyC,EAAOC,SAAS1C,GAAWU,KAAKI,GAChC2B,EAAOE,YACPF,EAAOG,eAAe5C,GAAW2C,aAQ/BE,EAA0B,SAAC7C,EAAmBc,GAChDuB,GAAsB,EACtBI,EAAOK,OAAO9C,GAAayC,EAAOK,OAAO9C,IAAc,GACvDyC,EAAOK,OAAO9C,GAAWU,KAAKI,GAC9B2B,EAAOM,YACPN,EAAOG,eAAe5C,GAAW+C,aA+B/BC,EAAmC,WACrCb,EAAoBpC,QAAQ,SAACkD,UAAQV,GAAaU,EAAGR,MA+InDA,EAAyB,CAC3BvC,KAAAA,EACA6C,UAAW,EACXJ,UAAW,EACXO,UAAW,EACXN,eAAgB,GAChBE,OAAQ,GACRJ,SAAU,GACVS,QAAS,GACTC,UA9BwB,SAACpD,UACpBA,EAIEqD,QAAQZ,EAAOa,UAAUtD,GAAWZ,QAHhCiD,GA6BXkB,YAlB0B,SAACvD,UACtBA,EAIEqD,QAAQZ,EAAOe,YAAYxD,GAAWZ,QAHlCkD,GAiBXgB,UAlEwB,SAACtD,UACpBA,EAIDyC,EAAOK,OAAO9C,GACPyC,EAAOK,OAAO9C,GAGlB,GAPIyC,EAAOK,QAiElBU,YAlD0B,SAACxD,UACtBA,EAIDyC,EAAOC,SAAS1C,GACTyC,EAAOC,SAAS1C,GAGpB,GAPIyC,EAAOC,UAiDlBf,KAlHmB,SAAC8B,SACI,mBAAbA,EAAiChB,GAEvCL,GACDqB,EAAShB,GAGbN,EAAoBzB,KAAK+C,GAClBhB,IA2GPiB,MAlGoB,SAAC1D,EAAmByD,SAChB,mBAAbA,EACAhB,KAGXL,EAAcA,GAAe,IACZpC,IAAcyC,EAAOG,eAAe5C,GACjDyD,EAAShB,GACFL,EAAYpC,KACnBoC,EAAYpC,GAAW2D,sBAAiBvB,EAAYpC,GAAW2D,WAAa,KAAKF,KAG9EhB,IAuFPmB,OAjFqB,kBACrBrB,GAAY,EAELE,UAiFJ,CACHrB,kBA9OgC,SAACpB,MAC7ByC,EAAOG,eAAe5C,UAAqByC,EAE/CA,EAAOG,eAAe5C,GAAa,CAC/BkD,UAAW,EACXH,UAAW,EACXJ,UAAW,IAyOfE,cAAAA,EACAL,gBAAAA,EACAN,gBAnO8B,SAAClC,OAC1ByC,EAAOG,eAAe5C,UAAqByC,EAEhDA,EAAOG,eAAe5C,GAAWkD,YACjCT,EAAOS,aAgOPnB,KA7LmB,SAAC/B,EAAmBc,EAAmBC,OACrD0B,EAAOG,eAAe5C,UAAqByC,ED5E1B,UC8Ea1B,GAAYlC,EAAWmD,SAASjB,GAAYA,ED7EzD,QCgFhByB,EAAgBxC,EAAWc,GAC3B+B,EAAc7C,EAAWc,IAuL/BI,aAhL2B,SAAClB,IAC3ByC,EAAOU,QAAQnB,SAAShC,IAAcyC,EAAOU,QAAQzC,KAAKV,IAgL3DgD,uBAAAA,EACAtB,UAlKwB,SAAC1B,IACzBoC,EAAcA,GAAe,IACjBpC,GAAaoC,EAAYpC,IAAc,GACnDoC,EAAYpC,GAAa,CACrB2B,MAAM,EACNgC,UAAWvB,EAAYpC,GAAW2D,WAAa,KA8JnD7B,WAtJyB,SAAC9B,OAErBA,SACMgD,IAGS,OAAhBZ,GAAwBA,EAAYpC,KACpCoC,EAAYpC,GAAW2B,MAAO,EAG1BS,EAAYpC,GAAW2D,WACvBvB,EAAYpC,GAAW2D,UAAU5D,QAAQ,SAAC0D,UAAclB,GAAakB,EAAShB,OA4ItFA,OAAAA,GE3OWoB,CAAe3D,GAE1BI,EAAMhB,KAAKiB,KAAMjB,KAAK2B,IAAIwB,aACrBqB,mBCrCb,SAAS3E,EAAQgB,UACNkD,QAAQnE,MAAMC,QAAQgB,ICDjC,SAAS4D,EAAS5D,UACPkD,QAAyB,iBAAVlD,GCD1B,SAAS6D,EAAS7D,UACPkD,QAAyB,iBAAVlD,GCD1B,SAAS8D,EAAQ9D,EAAe+D,UAExBA,aAAiBC,OACVD,EAAM3D,KAAKJ,GACM,iBAAV+D,GACP,IAAIC,OAAOD,GAAO3D,KAAKJ,GCDtC,SAASiE,EAAOjE,EAAckE,UAEtBnF,MAAMC,QAAQkF,IAAS,CAAC,SAAU,SAAU,WAAWrC,WAAgB7B,IAChEkE,EAAKrC,SAAS7B,GAIL,iBAATkE,GAAsC,iBAAVlE,GAC5BkE,EAAKrC,SAAS7B,GCZ7B,SAASmE,EAAOnE,EAAiBkE,UACtBlE,IAAUkE,ECDrB,SAASE,EAAUpE,OACTqE,GAAmBC,MAAMC,WAAWvE,MAAYsE,MAAME,OAAOxE,KAAWyE,SAASzE,UAChFkD,QAAQmB,GCDnB,SAASK,EAAQ1E,UACRA,IAEMoE,EAAUpE,GACA,IAAVA,EACAA,EAAMP,eAAe,UACJ,IAAjBO,EAAMf,OACW,WAAjBO,EAAOQ,IACuB,IAA9B2E,OAAOC,KAAK5E,GAAOf,QCRlC,SAAS4F,EAAY7E,EAAqBkE,UAC/BE,EAAUpE,IAAUoE,EAAUF,IAASM,OAAOxE,GAASwE,OAAON,GCDzE,SAASY,EAAoB9E,EAAqBkE,UACvCE,EAAUpE,IAAUoE,EAAUF,IAASM,OAAOxE,IAAUwE,OAAON,GCD1E,SAASa,EAAS/E,EAAqBkE,UAC5BE,EAAUpE,IAAUoE,EAAUF,IAASM,OAAOxE,GAASwE,OAAON,GCDzE,SAASc,EAAiBhF,EAAqBkE,UACpCE,EAAUpE,IAAUoE,EAAUF,IAASM,OAAOxE,IAAUwE,OAAON,GCF1E,SAASe,EAAajF,EAAsBkE,UACjClE,EAAMf,SAAWiF,EZG5BlF,EAAQkG,aAAe,aCAvBtB,EAASsB,aAAe,cCAxBrB,EAASqB,aAAe,cCOxBpB,EAAQoB,aAAe,aCOvBjB,EAAOiB,aAAe,YCdtBf,EAAOe,aAAe,YCCtBd,EAAUc,aAAe,eCUzBR,EAAQQ,aAAe,aCVvBL,EAAYM,MAAQ,KCApBL,EAAoBK,MAAQ,MCA5BJ,EAASI,MAAQ,KCAjBH,EAAiBG,MAAQ,MCDzBF,EAAaC,aAAe,kBCe5B,MCbA,SAAqBE,kBAENC,OACDH,EAAuBE,EAAMC,GAAMH,aACnCC,EAAgBC,EAAMC,GAAMF,MAE9BD,IACAE,EAAMF,GAAgB,kBAAcE,EAAMC,SAAND,eAGpCD,IACAC,EAAMD,GAASC,EAAMC,SATxB,IAAMA,KAAgBD,IAAhBC,UAaJD,EDkBIE,CApBa,CACxBtG,QAAAA,EACA4E,SAAAA,EACAC,SAAAA,EACAC,QAAAA,EACAG,OAAAA,EACAE,OAAAA,EACAC,UAAAA,EACAM,QAAAA,EACAG,YAAAA,EACAC,oBAAAA,EACAC,SAAAA,EACAC,iBAAAA,EACAO,WEhCJ,SAAoBvF,EAAsBkE,UAC/BlE,EAAMf,OAASiF,GFgCtBsB,mBGjCJ,SAA4BxF,EAAsBkE,UACvClE,EAAMf,QAAUiF,GHiCvBuB,YIlCJ,SAAqBzF,EAAsBkE,UAChClE,EAAMf,OAASiF,GJkCtBwB,oBKnCJ,SAA6B1F,EAAsBkE,UACxClE,EAAMf,QAAUiF,GLmCvBe,aAAAA,IM7BJ,SAASI,EAAKA,EAAmBrF,MAET,mBAATqF,8BAFsCM,mCAAAA,wBAIpB,IAAzBN,gBAAKrF,UAAU2F,UACT,IAAIC,qCAAmC5F,eCR1B6F,SAAS,cAATA,GAA3B,IAEMC,EAAmB,SAACC,EAAahG,UACnCgG,EAAYtG,eAAeM,IAAsC,mBAAtBgG,EAAYhG,IAGrDiG,EAAoB,eAACC,yDAA4B,GAC7CF,wUAAgCX,EAAUa,SAE3B,mBAAVC,MACA,SAAClG,OACEmG,EAAsB,IAAID,MAAMH,EAAa,CAC/CK,IAAK,SAAChB,EAAOiB,MACJP,EAAOV,EAAOiB,UAEZ,sCAAIV,2BAAAA,yBACPW,gBAAWlB,EAAMiB,GAASrG,UAAU2F,IAC7BQ,aAIZA,GAKR,SAACnG,UAAU2E,OAAOC,KAAKmB,GAAaQ,OAAO,SAACC,EAAUH,UACpDP,EAAOC,EAAaM,IAEzBG,EAASH,GAAU,sCAAIV,2BAAAA,yBACnBW,gBAAWP,EAAYM,GAASrG,UAAU2F,IACnCa,GAGJA,GAPoCA,GAQ5C,MCnCP,SAASC,EAAS1G,EAAcI,EAAqBvB,UACzB,IAAIsB,EAASH,EAAMI,EAAOvB,GACrCkC,IAAIwB,cAGrBmE,EAASC,QAAUC,QACnBF,EAASG,QAAU,IAAIZ,EAAQ,IAC/BS,EAAST,QAAUA,EACnBS,EAASI,SCNT,SAAkBzG,MAEM,mBAATA,KAAyBA,aAAgBe,eAC1C,IAAIrC,2CAAyCsB,qCAIjC,IAAXA,IACT,MAAO0G,UACE,IDFfL,EAASM,KzBbqB,OyBc9BN,EAASO,KzBbqB"} \ No newline at end of file diff --git a/documentation/getting_started/callbacks.md b/documentation/getting_started/callbacks.md index ad16f48b..149afc78 100644 --- a/documentation/getting_started/callbacks.md +++ b/documentation/getting_started/callbacks.md @@ -1,6 +1,6 @@ -# The `.after()` callback +# `.after()` -> Since 6.4.0 +> Since 7.0.0 The after callback is a function that can be chained to a passable suite and allows invoking a callback whenever a certain field has finished running, regardless of whether it passed or failed. It accepts two arguments: `fieldName` and `callback`. You may chain multiple callbacks to the same field. @@ -36,7 +36,7 @@ passable('SendEmailForm', (test) => { }); ``` -# The `.done()` callback +# `.done()` > Since 6.1.0 @@ -76,23 +76,39 @@ passable('SendEmailForm', (test) => { }).done(reportToServer).done(promptUserQuestionnaire); ``` -In the example above, whenever the validation completes, the following functions will get called, with the [validation result object](./result.md) as an argument: +# `.cancel()` + +> Since 7.0.0 + +When running your validation suite multiple times in a short amount of time - for example, when validating user inputs upon change, your async validations may finish after you already started running the suite again. This will cause the `.done()` and `.after()` callbacks of the previous run to be run in proximity to the `.done()` and `.after()` callbacks of the current run. + +Depending on what you do in your callbacks, this can lead to wasteful action, or to validation state rapidly changing in front of the user's eyes. + +To combat this, there's the `.cancel()` callback, which cancels any pending `.done()` and `.after()` callbacks. + +You can use it in many ways, but the simplistic way to look at it is this: You need to keep track of your cancel callback in a scope that's still going to be accessible in the next run. + +Example: -1. ```js -(res) => { - if (res.hasErrors()) { - showValidationErrors(res.errors) +let cancel = null; + +// this is a simple event handler +const handleChange = (e) => { + + if (cancel) { + cancel(); // now, if cancel already exists, it will cancel any pending callbacks } -} -``` -2. -```js -reportToServer -``` + // you should ideally import your suite from somewhere else, this is here just for the demonstration + const result = passable('MyForm', (test) => { + // some async validations go here + }); -3. -```js -promptUserQuestionnaire + result.done((res) => { + // do something + }); + + cancel = result.cancel; // save the cancel callback aside +} ``` \ No newline at end of file diff --git a/src/core/Passable/index.js b/src/core/Passable/index.js index d568201d..ee826e35 100644 --- a/src/core/Passable/index.js +++ b/src/core/Passable/index.js @@ -13,9 +13,7 @@ class Passable { specific: Specific; res: PassableResult; test: TestProvider; - pending: Array; - - pending = []; + pending: Array = []; /** * Initializes a validation suite, creates a new passableResult instance and runs pending tests @@ -53,7 +51,17 @@ class Passable { * @param {String} fieldName name of the field to test against * @return {Boolean} */ - hasRemainingPendingTests = (fieldName: string) => this.pending.some((test) => test.fieldName === fieldName); + hasRemainingPendingTests = (fieldName?: string) => { + if (!this.pending.length) { + return false; + } + + if (fieldName) { + return this.pending.some((test) => test.fieldName === fieldName); + } + + return !!this.pending.length; + } /** * Test function passed over to the consumer. @@ -104,25 +112,9 @@ class Passable { statement: string } = test; - let isAsync: boolean = typeof test.then === 'function'; + const isAsync: boolean = typeof test.then === 'function'; let testResult: AnyValue; - - if (!isAsync) { - try { - testResult = test(); - } catch (e) { - testResult = false; - } - - if (testResult && typeof testResult.then === 'function') { - isAsync = true; - - // $FlowFixMe - test = testResult; - } - } - if (isAsync) { this.res.markAsync(fieldName); @@ -131,11 +123,18 @@ class Passable { if (!this.hasRemainingPendingTests(fieldName)) { this.res.markAsDone(fieldName); } + + if (!this.hasRemainingPendingTests()) { + this.res.markAsDone(); + } }; const fail: Function = () => { // order is important here! fail needs to be called before `done`. - this.res.fail(fieldName, statement, severity); + + if (this.pending.includes(test)) { + this.res.fail(fieldName, statement, severity); + } done(); }; @@ -143,15 +142,34 @@ class Passable { // $FlowFixMe test.then(done, fail); } catch (e) { - fail(); + fail(test); } } else { + try { + testResult = test(); + } catch (e) { + testResult = false; + } + + // if is async after all + if (testResult && typeof testResult.then === 'function') { + testResult.fieldName = fieldName; + testResult.statement = statement; + testResult.severity = severity; + + // $FlowFixMe + return this.addPendingTest(testResult); + } + + // explicitly false if (testResult === false) { this.res.fail(fieldName, statement, severity); } + this.clearPendingTest(test); } + this.res.bumpTestCounter(fieldName); } diff --git a/src/core/passableResult/index.js b/src/core/passableResult/index.js index df013848..37354ee4 100644 --- a/src/core/passableResult/index.js +++ b/src/core/passableResult/index.js @@ -16,6 +16,7 @@ const passableResult: Function = (name: string): PassableResult => { let asyncObject: AsyncObject = null; let hasValidationErrors: boolean = false; let hasValidationWarnings: boolean = false; + let cancelled: boolean = false; /** * Initializes specific field's counters @@ -97,7 +98,7 @@ const passableResult: Function = (name: string): PassableResult => { * regardless of success or failure */ const runCompletionCallbacks: Function = () => { - completionCallbacks.forEach((cb) => cb(output)); + completionCallbacks.forEach((cb) => !cancelled && cb(output)); }; /** @@ -117,16 +118,19 @@ const passableResult: Function = (name: string): PassableResult => { * Marks an async field as done * @param {string} fieldName the name of the field marked as done */ - const markAsDone: Function = (fieldName: string) => { + const markAsDone: Function = (fieldName?: string) => { + + if (!fieldName) { + return runCompletionCallbacks(); + } + if (asyncObject !== null && asyncObject[fieldName]) { asyncObject[fieldName].done = true; // run field callbacks set in `after` if (asyncObject[fieldName].callbacks) { - asyncObject[fieldName].callbacks.forEach((callback) => callback(output)); + asyncObject[fieldName].callbacks.forEach((callback) => !cancelled && callback(output)); } - - runCompletionCallbacks(); } }; @@ -168,6 +172,15 @@ const passableResult: Function = (name: string): PassableResult => { return output; }; + /** + * cancels done/after callbacks. They won't invoke when async operations complete + */ + const cancel: Function = () => { + cancelled = true; + + return output; + }; + /** * Gets all the errors of a field, or of the whole object * @param {string} [fieldName] - The name of the field. @@ -242,7 +255,8 @@ const passableResult: Function = (name: string): PassableResult => { getErrors, getWarnings, done, - after + after, + cancel }; return { diff --git a/src/core/passableResult/spec.js b/src/core/passableResult/spec.js index de8bb39d..4532dcfe 100644 --- a/src/core/passableResult/spec.js +++ b/src/core/passableResult/spec.js @@ -1,5 +1,6 @@ import passable from '../..'; import passableResult from './index'; +import { test } from 'mocha'; import { WARN, FAIL } from '../../constants'; import { expect } from 'chai'; import { excludeFromResult } from '../../../config/test-setup'; @@ -7,10 +8,10 @@ import { noop, sample } from 'lodash'; import sinon from 'sinon'; import faker from 'faker'; -const rejectLater = () => new Promise((res, rej) => { +const rejectLater = (time = 500) => new Promise((res, rej) => { setTimeout(() => { sample([res, rej])(); - }, 500); + }, time); }); describe('module: passableResult', () => { @@ -235,6 +236,26 @@ describe('module: passableResult', () => { expect(values).to.deep.equal([1, 2, 3, 4]); }); }); + + test('done callbacks run exactly once', (done) => { + const spy1 = sinon.spy(); + const spy2 = sinon.spy(); + + passable(faker.lorem.word(), (test) => { + test('t1', faker.lorem.sentence(), async() => await rejectLater()); + test('t2', faker.lorem.sentence(), Promise.resolve()); + test('t3', faker.lorem.sentence(), () => Promise.reject()); + test('t4', faker.lorem.sentence(), () => enforce(1).equals(2)); + }).done(spy1).done(spy2) + .after('t1', noop).after('t2', noop).after('t3', noop).after('t4', noop); + + setTimeout(() => { + expect(spy1.callCount).to.equal(1); + expect(spy2.callCount).to.equal(1); + done(); + }, 550); + + }); }); describe('method: after', () => { @@ -314,6 +335,53 @@ describe('module: passableResult', () => { }); }); + describe('method: cancel', () => { + let done1, done2, after1, after2, f1, f2, f3, result; + + beforeEach(() => { + done1 = sinon.spy(); + done2 = sinon.spy(); + after1 = sinon.spy(); + after2 = sinon.spy(); + f1 = faker.lorem.word(); + f2 = faker.lorem.word(); + f3 = faker.lorem.word(); + + result = passable(faker.lorem.word(), (test) => { + test(f1, faker.lorem.sentence(), rejectLater()); + test(f2, faker.lorem.sentence(), Promise.resolve()); + test(f3, faker.lorem.sentence(), new Promise((...args) => { + setTimeout(() => { + sample(args)(); + }, 200); + })); + }).done(done1).done(done2).after(f1, after1).after(f2, after2); + }); + + it('Should cancel all async callbacks when invoked immediately', () => { + result.cancel(); + expect(done1.callCount).to.equal(0); + expect(done2.callCount).to.equal(0); + expect(after1.callCount).to.equal(0); + expect(after2.callCount).to.equal(0); + }); + + it('Should cancel remaining async callbacks when invoked', (done) => { + setTimeout(() => { + result.cancel(); + }, 250); + + setTimeout(() => { + expect(done1.callCount).to.equal(0); + expect(done2.callCount).to.equal(0); + expect(after1.callCount).to.equal(0); + expect(after2.callCount).to.equal(1); + done(); + }, 600); + }); + + }); + describe('method: getErrors', () => { let testObject; beforeEach(() => { diff --git a/src/types.js b/src/types.js index 21cd81b0..f4f167fa 100644 --- a/src/types.js +++ b/src/types.js @@ -98,7 +98,8 @@ declare type PassableOutput = { getErrors: (fieldName?: string) => string[] | { [fieldName: string]: string[] }, getWarnings: (fieldName?: string) => string[] | { [fieldName: string]: string[] }, done: ((output: PassableOutput) => void) => PassableOutput, - after: ((output: PassableOutput) => void) => PassableOutput + after: ((output: PassableOutput) => void) => PassableOutput, + cancel: () => PassableOutput }; declare type PassableResult = { @@ -110,7 +111,7 @@ declare type PassableResult = { addToSkipped: (fieldName: string) => void, runCompletionCallbacks: () => void, markAsync: (fieldName: string) => void, - markAsDone: (fieldName: string) => void, + markAsDone: (fieldName?: string) => void, output: PassableOutput };