quival 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,7 +29,7 @@ There are 2 ways to start using `quival` in your project.
29
29
  Get the script from [jsDelivr CDN page](https://www.jsdelivr.com/package/npm/quival) and include it in your HTML page.
30
30
 
31
31
  ```html
32
- <script src="https://cdn.jsdelivr.net/npm/quival@0.3.x/dist/quival.min.js"></script>
32
+ <script src="https://cdn.jsdelivr.net/npm/quival@0.4.x/dist/quival.min.js"></script>
33
33
  ```
34
34
 
35
35
  Extract `Validator` class from `quival` global variable, and you are good to go.
@@ -83,6 +83,7 @@ Validator.addChecker(
83
83
 
84
84
  // Prepare arguments
85
85
  const data = {
86
+ refcode: '1bc',
86
87
  username: 'idea💡',
87
88
  name: '',
88
89
  email: 'test',
@@ -98,6 +99,15 @@ const data = {
98
99
  };
99
100
 
100
101
  const rules = {
102
+ refcode: [
103
+ 'required',
104
+ function (attribute, value) { // Closure rule
105
+ return {
106
+ success: /^[a-z]/i.test(value),
107
+ message: 'The :attribute field must start with a letter.',
108
+ };
109
+ },
110
+ ],
101
111
  username: ['required', 'ascii', 'min:3'],
102
112
  name: ['required', 'min:3'],
103
113
  email: ['required', 'email'],
@@ -138,6 +148,9 @@ The produced error messages for the code snippet above.
138
148
 
139
149
  ```json
140
150
  {
151
+ "refcode": [
152
+ "The refcode field must start with a letter."
153
+ ],
141
154
  "username": [
142
155
  "The username field must only contain single-byte alphanumeric characters and symbols."
143
156
  ],
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * quival v0.3.4 (https://github.com/apih/quival)
2
+ * quival v0.4.0 (https://github.com/apih/quival)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * quival v0.3.4 (https://github.com/apih/quival)
2
+ * quival v0.4.0 (https://github.com/apih/quival)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * quival v0.3.4 (https://github.com/apih/quival)
2
+ * quival v0.4.0 (https://github.com/apih/quival)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * quival v0.3.4 (https://github.com/apih/quival)
2
+ * quival v0.4.0 (https://github.com/apih/quival)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
package/dist/quival.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * quival v0.3.4 (https://github.com/apih/quival)
2
+ * quival v0.4.0 (https://github.com/apih/quival)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
@@ -1368,10 +1368,9 @@ var quival = (function (exports) {
1368
1368
  for (const [attribute, attributeRules] of Object.entries(rules)) {
1369
1369
  const attributes = attribute.includes('*') ? this.parseWildcardAttribute(attribute) : [attribute];
1370
1370
  for (const attribute of attributes) {
1371
- const parsedAttributeRules = {};
1371
+ const parsedAttributeRules = [];
1372
1372
  for (const attributeRule of this.parseAttributeRules(attributeRules)) {
1373
- const [rule, parameters] = this.parseAttributeRule(attributeRule);
1374
- parsedAttributeRules[rule] = parameters;
1373
+ parsedAttributeRules.push(this.parseAttributeRule(attributeRule));
1375
1374
  }
1376
1375
  parsedRules[attribute] = parsedAttributeRules;
1377
1376
  }
@@ -1398,13 +1397,17 @@ var quival = (function (exports) {
1398
1397
  parseAttributeRules(rules) {
1399
1398
  if (Array.isArray(rules)) {
1400
1399
  return rules;
1400
+ } else if (typeof rules === 'function') {
1401
+ return [rules];
1401
1402
  } else {
1402
1403
  return String(rules).split('|');
1403
1404
  }
1404
1405
  }
1405
1406
  parseAttributeRule(rule) {
1406
1407
  if (Array.isArray(rule)) {
1407
- return [rule.shift() ?? '', rule];
1408
+ return [rule[0] ?? '', rule.slice(1)];
1409
+ } else if (typeof rule === 'function') {
1410
+ return [rule, []];
1408
1411
  }
1409
1412
  const index = rule.indexOf(':');
1410
1413
  if (index === -1) {
@@ -1418,39 +1421,61 @@ var quival = (function (exports) {
1418
1421
  this.#errors = new ErrorBag();
1419
1422
  const tasks = [];
1420
1423
  const skippedAttributes = [];
1424
+ for (const [attribute, rules] of Object.entries(this.#rules)) {
1425
+ for (const [rule] of rules) {
1426
+ if (
1427
+ rule === '' ||
1428
+ typeof rule === 'function' ||
1429
+ typeof this.#checkers[toCamelCase('check_' + rule)] === 'function' ||
1430
+ Validator.#dummyRules.includes(rule)
1431
+ )
1432
+ continue;
1433
+ throw new Error(`Invalid validation rule: ${rule}`);
1434
+ }
1435
+ }
1421
1436
  for (const [attribute, rules] of Object.entries(this.#rules)) {
1422
1437
  let value = this.getValue(attribute);
1423
- if (Object.hasOwn(rules, 'sometimes') && typeof value === 'undefined') {
1438
+ const hasRule = (ruleName) => rules.some((rule) => rule[0] === ruleName);
1439
+ if (hasRule('sometimes') && typeof value === 'undefined') {
1424
1440
  skippedAttributes.push(attribute);
1425
1441
  continue;
1426
1442
  }
1427
1443
  tasks.push(async () => {
1428
- const doBail = this.#alwaysBail || Object.hasOwn(rules, 'bail');
1429
- const isNullable = Object.hasOwn(rules, 'nullable');
1444
+ const doBail = this.#alwaysBail || hasRule('bail');
1445
+ const isNullable = hasRule('nullable');
1430
1446
  let noError = true;
1431
- for (const [rule, parameters] of Object.entries(rules)) {
1447
+ for (const [rule, parameters] of rules) {
1432
1448
  if (
1433
1449
  rule === '' ||
1434
- (!Validator.#implicitRules.includes(rule) &&
1450
+ (typeof rule !== 'function' &&
1451
+ !Validator.#implicitRules.includes(rule) &&
1435
1452
  (typeof value === 'undefined' || (typeof value === 'string' && value.trim() === '') || (isNullable && value === null)))
1436
1453
  ) {
1437
1454
  skippedAttributes.push(attribute);
1438
1455
  continue;
1439
1456
  }
1440
1457
  let result, success, message;
1441
- const camelRule = toCamelCase('check_' + rule);
1442
- if (typeof this.#checkers[camelRule] === 'function') {
1443
- result = await this.#checkers[camelRule](attribute, value, parameters);
1444
- } else if (Validator.#dummyRules.includes(rule)) {
1445
- result = true;
1446
- } else {
1458
+ const checker = (() => {
1459
+ if (typeof rule === 'function') {
1460
+ return rule;
1461
+ } else {
1462
+ const checker = this.#checkers[toCamelCase('check_' + rule)] ?? null;
1463
+ if (checker === null && Validator.#dummyRules.includes(rule)) {
1464
+ return () => true;
1465
+ }
1466
+ return checker;
1467
+ }
1468
+ })();
1469
+ if (checker === null) {
1447
1470
  throw new Error(`Invalid validation rule: ${rule}`);
1448
1471
  }
1472
+ result = await checker.call(this.#checkers, attribute, value, parameters);
1449
1473
  if (typeof result === 'boolean') {
1450
- success = result;
1451
- } else {
1452
- ({ success, message } = result);
1474
+ result = {
1475
+ success: result,
1476
+ };
1453
1477
  }
1478
+ ({ success, message = '' } = result);
1454
1479
  if (!success) {
1455
1480
  noError = false;
1456
1481
  message = isEmpty(message) ? this.getMessage(attribute, rule) : message;
@@ -1469,7 +1494,13 @@ var quival = (function (exports) {
1469
1494
  if (!(await task())) break;
1470
1495
  }
1471
1496
  } else {
1472
- await Promise.allSettled(tasks.map((task) => task()));
1497
+ await Promise.allSettled(tasks.map((task) => task())).then((results) => {
1498
+ for (const result of results) {
1499
+ if (result.status === 'rejected') {
1500
+ throw result.reason;
1501
+ }
1502
+ }
1503
+ });
1473
1504
  this.#errors.sortByKeys(Object.keys(this.#rules));
1474
1505
  }
1475
1506
  this.#skippedAttributes = skippedAttributes.filter((value, index, array) => array.indexOf(value) === index);
@@ -1486,6 +1517,9 @@ var quival = (function (exports) {
1486
1517
  return !(await this.passes());
1487
1518
  }
1488
1519
  getMessage(attribute, rule) {
1520
+ if (typeof rule === 'function') {
1521
+ return '';
1522
+ }
1489
1523
  const value = this.getValue(attribute);
1490
1524
  attribute = this.getPrimaryAttribute(attribute);
1491
1525
  let message;
@@ -1529,9 +1563,11 @@ var quival = (function (exports) {
1529
1563
  if (index !== -1) {
1530
1564
  message = message.replaceAll(':index', index).replaceAll(':position', index + 1);
1531
1565
  }
1532
- const camelRule = toCamelCase('replace_' + rule);
1533
- if (typeof this.#replacers[camelRule] === 'function') {
1534
- message = this.#replacers[camelRule](message, attribute, rule, parameters);
1566
+ if (typeof rule === 'string') {
1567
+ const replacer = this.#replacers[toCamelCase('replace_' + rule)] ?? null;
1568
+ if (replacer) {
1569
+ message = replacer.call(this.#replacers, message, attribute, rule, parameters);
1570
+ }
1535
1571
  }
1536
1572
  return message;
1537
1573
  }
@@ -1588,7 +1624,7 @@ var quival = (function (exports) {
1588
1624
  return false;
1589
1625
  }
1590
1626
  for (const rule of rules) {
1591
- if (this.#rules[attribute].hasOwnProperty(rule)) {
1627
+ if (this.#rules[attribute].some((attributeRule) => attributeRule[0] === rule)) {
1592
1628
  return true;
1593
1629
  }
1594
1630
  }
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * quival v0.3.4 (https://github.com/apih/quival)
2
+ * quival v0.4.0 (https://github.com/apih/quival)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
6
- var quival=function(e){"use strict";function t(e){return e.replace(/[-_]/g," ").replace(/\s+/," ").trim().replace(/(\s\w)/g,(e=>e[1].toUpperCase()))}function r(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function s(e,t=""){return Object.keys(e).reduce(((r,i)=>{const c=t?`${t}.${i}`:i;return"object"==typeof e[i]&&null!==e[i]?Object.assign(r,s(e[i],c)):r[c]=e[i],r}),{})}function i(e){const t=[];let r="",s=!1;for(let i=0;i<e.length;i++){const c=e[i];'"'===c?s&&'"'===e[i+1]?(r+='"',i++):(s=!s,s&&(r=r.trim())):","!==c||s?r+=c:(t.push(r),r="")}return t.push(r),t}function c(e){if(n(e)||"string"!=typeof e)return new Date("");if(e instanceof Date)return e;let t,r,s,i,c,a,u,h;const l=e=>e&&/^\d*$/.test(e)?parseInt(e):e;if(null!==(t=e.match(/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{2,4})\s?((\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?)?/i)))[,i,s,r,,c=0,a=0,,u=0,h="am"]=t.map(l);else if(null!==(t=e.match(/^(\d{2,4})[.\/-](\d{1,2})[.\/-](\d{1,2})\s?((\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?)?/i))||null!==(t=e.match(/^(\d{4})(\d{2})(\d{2})\s?((\d{2})(\d{2})((\d{2}))?\s?(am|pm)?)?/i)))[,r,s,i,,c=0,a=0,,u=0,h="am"]=t.map(l);else if(t=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{4})[.\/-](\d{2})[.\/-](\d{2})/i))[,c,a,,u,h="am",r,s,i]=t.map(l);else if(t=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{2})[.\/-](\d{2})[.\/-](\d{4})/i))[,c,a,,u,h="am",i,s,r]=t.map(l);else{if(!(t=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?/i)))return new Date(e);{const e=new Date;r=e.getFullYear(),s=e.getMonth()+1,i=e.getDate(),[,c=0,a=0,,u=0,h="am"]=t.map(l)}}return r>=10&&r<100&&(r+=2e3),"pm"===h.toLowerCase()&&c<12&&(c+=12),new Date(`${r}-${s}-${i} ${c}:${a}:${u}`)}function a(e,t){if(n(e))return new Date("");t=t.split("");const r={Y:"(\\d{4})",y:"(\\d{2})",m:"(\\d{2})",n:"([1-9]\\d?)",d:"(\\d{2})",j:"([1-9]\\d?)",G:"([1-9]\\d?)",g:"([1-9]\\d?)",H:"(\\d{2})",h:"(\\d{2})",i:"(\\d{2})",s:"(\\d{2})",A:"(AM|PM)",a:"(am|pm)"};let s="^",i={years:-1,months:-1,days:-1,hours:-1,minutes:-1,seconds:-1,meridiem:-1},c=1;for(const e of t)Object.hasOwn(r,e)?(s+=r[e],-1!==["Y","y"].indexOf(e)?i.years=c++:-1!==["m","n"].indexOf(e)?i.months=c++:-1!==["d","j"].indexOf(e)?i.days=c++:-1!==["G","g","H","h"].indexOf(e)?i.hours=c++:"i"===e?i.minutes=c++:"s"===e?i.seconds=c++:-1!==["A","a"].indexOf(e)&&(i.meridiem=c++)):s+="\\"+e;s+="$";let a=e.match(new RegExp(s));if(null===a)return new Date("");a=a.map((e=>e&&/^\d*$/.test(e)?parseInt(e):e));const u=new Date;let h=a[i.years],l=a[i.months],o=a[i.days],d=a[i.hours]??0,p=a[i.minutes]??0,f=a[i.seconds]??0,g=a[i.meridiem]??"am";return h||l||o?!h||l||o?h||!l||o?h||l||!o||(h=u.getFullYear(),l=u.getMonth()+1):(h=u.getFullYear(),o=1):(l=1,o=1):(h=u.getFullYear(),l=u.getMonth()+1,o=u.getDate()),h>=10&&h<100&&(h+=2e3),"pm"===g.toLowerCase()&&d<12&&(d+=12),new Date(`${h}-${l}-${o} ${d}:${p}:${f}`)}function n(e){return""===e||null==e}function u(e){const t=Number(e);return null!==e&&"boolean"!=typeof e&&"number"==typeof t&&!isNaN(t)}function h(e){return"[object Object]"===Object.prototype.toString.call(e)}function l(e){return e instanceof Date&&"Invalid Date"!==e.toDateString()}class o{#e;#t;constructor(e){this.#e={},this.#t={},this.validator=e}clearCaches(){this.#e={},this.#t={}}isDependent(e){const t=this.validator.getValue(e[0]);return e.slice(1).some((e=>e==t))}collectRequiredsThenTest(e,t,r,s){let i=[];for(const e of r)i.push(this.checkRequired(e,this.validator.getValue(e)));return!s(i)||this.checkRequired(e,t)}collectMissingsThenTest(e,t,r,s){let i=[];for(const e of r)i.push(this.checkMissing(e));return!s(i)||this.checkMissing(e)}testStringUsingRegex(e,t,r,s,i=!1){return("string"==typeof t||"number"==typeof t)&&(t=String(t),i||this.validator.hasRule(e,"ascii")?r.test(t):s.test(t))}compareValues(e,t,r,s){if(n(t))return!1;const i=r[0]??"";let c=this.validator.getValue(i);return c=void 0===c?u(i)?parseFloat(i,10):null:this.validator.getSize(i,c),!n(c)&&s(this.validator.getSize(e,t),c)}compareDates(e,t,r,s){const i=this.validator.getRule(e);if(!l(t=Object.hasOwn(i,"date_format")?a(t,i.date_format[0]):c(t)))return!1;const n=r[0]??"";let u=this.validator.getValue(n);if(void 0===u)u=c(n);else{const e=this.validator.getRule(n);u=Object.hasOwn(e,"date_format")?a(u,e.date_format[0]):c(u)}return!!l(u)&&s(t.getTime(),u.getTime())}checkArray(e,t,r){if(!Array.isArray(t)&&!h(t))return!1;if(r&&r.length>0)for(const e of Object.keys(t))if(!r.includes(e))return!1;return!0}checkList(e,t,r){return Array.isArray(t)}checkBoolean(e,t,r){return[!0,!1,0,1,"0","1"].includes(t)}checkDate(e,t,r){return l(c(t))}checkFile(e,t,r){return t instanceof File}checkInteger(e,t,r){return String(parseInt(t,10))===String(t)}checkNumeric(e,t,r){return u(t)}checkString(e,t,r){return"string"==typeof t}checkDecimal(e,t,r){if(!this.checkNumeric(e,t))return!1;const s=(String(t).split(".")[1]??"").length;return 1===r.length?s==r[0]:s>=r[0]&&s<=r[1]}checkMultipleOf(e,t,r){if(!u(t)||!u(r[0]))return!1;const s=parseInt(t,10),i=parseInt(r[0],10);return(0!==s||0!==i)&&(0===s||0!==i&&s%i==0)}checkAccepted(e,t,r){return["yes","on","1",1,!0,"true"].includes(t)}checkAcceptedIf(e,t,r){return!this.isDependent(r)||this.checkAccepted(e,t,r)}checkDeclined(e,t,r){return["no","off","0",0,!1,"false"].includes(t)}checkDeclinedIf(e,t,r){return!this.isDependent(r)||this.checkDeclined(e,t,r)}checkRequired(e,t,r){return!n(t)&&(Array.isArray(t)?t.length>0:t instanceof File?t.size>0:(t=String(t).replace(/\s/g,"")).length>0)}checkRequiredArrayKeys(e,t,r){if(!this.checkArray(e,t))return!1;const s=Object.keys(t);for(const e of r)if(!s.includes(e))return!1;return!0}checkRequiredIf(e,t,r){return!this.isDependent(r)||this.checkRequired(e,t)}checkRequiredIfAccepted(e,t,r){return!this.checkAccepted(r[0],this.validator.getValue(r[0]))||this.checkRequired(e,t)}checkRequiredIfDeclined(e,t,r){return!this.checkDeclined(r[0],this.validator.getValue(r[0]))||this.checkRequired(e,t)}checkRequiredUnless(e,t,r){return!!this.isDependent(r)||this.checkRequired(e,t)}checkRequiredWith(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>e.includes(!0)))}checkRequiredWithAll(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>!e.includes(!1)))}checkRequiredWithout(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>e.includes(!1)))}checkRequiredWithoutAll(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>!e.includes(!0)))}checkFilled(e,t,r){return void 0===t||this.checkRequired(e,t)}checkPresent(e,t,r){return void 0!==t}checkMissing(e,t,r){return!this.validator.hasAttribute(e)}checkMissingIf(e,t,r){return!this.isDependent(r)||this.checkMissing(e)}checkMissingUnless(e,t,r){return!!this.isDependent(r)||this.checkMissing(e)}checkMissingWith(e,t,r){return this.collectMissingsThenTest(e,t,r,(e=>e.includes(!1)))}checkMissingWithAll(e,t,r){return this.collectMissingsThenTest(e,t,r,(e=>!e.includes(!0)))}checkProhibited(e,t,r){return!this.checkRequired(e,t)}checkProhibitedIf(e,t,r){return!this.isDependent(r)||!this.checkRequired(e,t)}checkProhibitedUnless(e,t,r){return!!this.isDependent(r)||!this.checkRequired(e,t)}checkProhibits(e,t,r){if(this.checkRequired(e,t))for(const e of r)if(this.checkRequired(e,this.validator.getValue(e)))return!1;return!0}checkSize(e,t,r){return this.validator.getSize(e,t)===parseFloat(r[0])}checkMin(e,t,r){return this.validator.getSize(e,t)>=parseFloat(r[0])}checkMax(e,t,r){return this.validator.getSize(e,t)<=parseFloat(r[0])}checkBetween(e,t,r){return this.checkMin(e,t,[r[0]])&&this.checkMax(e,t,[r[1]])}checkDigits(e,t,r,s=(e,t)=>e===t){return!!function(e){return-1===String(e).search(/[^0-9]/)}(t=String(t??""))&&s(t.length,parseInt(r[0],10),parseInt(r[1]??0,10))}checkMinDigits(e,t,r){return this.checkDigits(e,t,r,((e,t)=>e>=t))}checkMaxDigits(e,t,r){return this.checkDigits(e,t,r,((e,t)=>e<=t))}checkDigitsBetween(e,t,r){return this.checkDigits(e,t,r,((e,t,r)=>e>=t&&e<=r))}checkAlpha(e,t,r){return this.testStringUsingRegex(e,t,/^[a-z]+$/i,/^[\p{L}\p{M}]+$/u,r.includes("ascii"))}checkAlphaDash(e,t,r){return this.testStringUsingRegex(e,t,/^[a-z0-9_-]+$/i,/^[\p{L}\p{M}\p{N}_-]+$/u,r.includes("ascii"))}checkAlphaNum(e,t,r){return this.testStringUsingRegex(e,t,/^[a-z0-9]+$/i,/^[\p{L}\p{M}\p{N}]+$/u,r.includes("ascii"))}checkAscii(e,t,r){return!/[^\x09\x10\x13\x0A\x0D\x20-\x7E]/.test(t)}checkRegex(e,t,r,s=!1){if("string"!=typeof t&&!u(t))return!1;const i=r.join(",");let[c,a,h]=i.match(/^\/(.*)\/([gimu]*)$/)??[];if(n(c))throw new Error(`Invalid regular expression pattern: ${i}`);h.includes("u")&&(a=a.replace(/\\A/g,"^").replace(/\\z/gi,"$").replace(/\\([pP])([CLMNPSZ])/g,"\\$1{$2}").replace(/\\\x\{([0-9a-f]+)\}/g,"\\u{$1}"));const l=new RegExp(a,h).test(t);return s?!l:l}checkNotRegex(e,t,r){return this.checkRegex(e,t,r,!0)}checkLowercase(e,t,r){return t===String(t).toLocaleLowerCase()}checkUppercase(e,t,r){return t===String(t).toLocaleUpperCase()}checkStartsWith(e,t,r){t=String(t);for(const e of r)if(t.startsWith(e))return!0;return!1}checkDoesntStartWith(e,t,r){return!this.checkStartsWith(e,t,r)}checkEndsWith(e,t,r){t=String(t);for(const e of r)if(t.endsWith(e))return!0;return!1}checkDoesntEndWith(e,t,r){return!this.checkEndsWith(e,t,r)}checkSame(e,t,r){return t===this.validator.getValue(r[0])}checkDifferent(e,t,r){for(const e of r){const r=this.validator.getValue(e);if(void 0!==r&&t===r)return!1}return!0}checkConfirmed(e,t,r){return this.checkSame(e,t,[e+"_confirmation"])}checkGt(e,t,r){return this.compareValues(e,t,r,((e,t)=>e>t))}checkGte(e,t,r){return this.compareValues(e,t,r,((e,t)=>e>=t))}checkLt(e,t,r){return this.compareValues(e,t,r,((e,t)=>e<t))}checkLte(e,t,r){return this.compareValues(e,t,r,((e,t)=>e<=t))}checkAfter(e,t,r){return this.compareDates(e,t,r,((e,t)=>e>t))}checkAfterOrEqual(e,t,r){return this.compareDates(e,t,r,((e,t)=>e>=t))}checkBefore(e,t,r){return this.compareDates(e,t,r,((e,t)=>e<t))}checkBeforeOrEqual(e,t,r){return this.compareDates(e,t,r,((e,t)=>e<=t))}checkDateEquals(e,t,r){return this.compareDates(e,t,r,((e,t)=>e===t))}checkDateFormat(e,t,r){const s=r[0].split(""),i={Y:"(\\d{4})",y:"(\\d{2})",m:"(\\d{2})",n:"([1-9]\\d?)",d:"(\\d{2})",j:"([1-9]\\d?)",G:"([1-9]\\d?)",g:"([1-9]\\d?)",H:"(\\d{2})",h:"(\\d{2})",i:"(\\d{2})",s:"(\\d{2})",A:"(AM|PM)",a:"(am|pm)"};let c="^";for(const e of s)Object.hasOwn(i,e)?c+=i[e]:c+="\\"+e;return c+="$",new RegExp(c).test(t)}checkContains(e,t,r){if(!this.checkArray(e,t))return!1;for(const e of r)if(!t.includes(e))return!1;return!0}checkDistinct(e,t,i){const c=this.validator.getPrimaryAttribute(e);if(!c.includes("*"))return!0;const a=c.indexOf("*"),n=c.substring(0,a-1);let u;Object.hasOwn(this.#e,n)?u=this.#e[n]:(u=JSON.stringify(s(this.validator.getValue(n)??{})),this.#e[n]=u);const h=i.includes("ignore_case"),l=!h&&i.includes("strict"),o=r(String(t));let d=`"${r(c.substring(a)).replaceAll("\\*",'[^."]+')}":`,p=0;return d+=l?"string"==typeof t?`"${o}"`:`${o}`:`(${o}|"${o}")`,d+="[,}]+",p+=u.match(new RegExp(d,"g"+(h?"i":"")))?.length??0,1===p}checkInArray(e,t,r){const i=this.validator.getPrimaryAttribute(r[0]);if(!i.includes("*"))return!1;const c=this.validator.getValue(i.split(".*")[0])??{};return Object.values(s(c)).some((e=>e==t))}checkIn(e,t,r){if(!this.checkArray(e,t)||!this.validator.hasRule(e,"array"))return r.some((e=>e==t));for(const e of Object.values(t))if(!r.some((t=>t==e)))return!1;return!0}checkNotIn(e,t,r){return!this.checkIn(e,t,r)}checkMimetypes(e,t,r){return!!this.checkFile(e,t)&&r.includes(t.type)}checkMimes(e,t,r){return!!this.checkFile(e,t)&&(r.includes("jpg")&&!r.includes("jpeg")&&r.push("jpeg"),r.includes("jpeg")&&!r.includes("jpg")&&r.push("jpg"),r.includes(t.name.split(".").pop().toLowerCase()))}checkExtensions(e,t,r){return this.checkMimes(e,t,r)}async checkImage(e,t,r){let s=this.checkMimes(e,t,["jpg","jpeg","png","gif","bmp","svg","webp"]);return s&&"undefined"!=typeof FileReader?(await new Promise(((e,r)=>{const s=new FileReader;s.onload=t=>e(t.target.result),s.onerror=r,s.readAsDataURL(t)})).then((async t=>{const r=new Image;r.src=t,await r.decode(),this.#t[e]=r})).catch((()=>{s=!1})),s):s}async checkDimensions(e,t,r){if(!this.checkImage(e,t)||!Object.hasOwn(this.#t,e))return!1;const s={};for(const e of r){const[t,r]=e.split("=",2);if("ratio"===t&&r.includes("/")){const[e,i]=r.split("/",2).map((e=>parseFloat(e,10)));s[t]=e/i}else s[t]=parseFloat(r,10)}const i=this.#t[e],c=i.naturalWidth,a=i.naturalHeight;return!(Object.hasOwn(s,"width")&&s.width!==c||Object.hasOwn(s,"height")&&s.height!==a||Object.hasOwn(s,"min_width")&&s.min_width>c||Object.hasOwn(s,"min_height")&&s.min_height>a||Object.hasOwn(s,"max_width")&&s.max_width<c||Object.hasOwn(s,"max_height")&&s.max_height<a)&&(!Object.hasOwn(s,"ratio")||Math.abs(s.ratio-c/a)<=1/(Math.max(c,a)+1))}checkEmail(e,t,r){if(!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(t)){return/^((?:[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]|[^\u0000-\u007F])+@(?:[a-zA-Z0-9]|[^\u0000-\u007F])(?:(?:[a-zA-Z0-9-]|[^\u0000-\u007F]){0,61}(?:[a-zA-Z0-9]|[^\u0000-\u007F]))?(?:\.(?:[a-zA-Z0-9]|[^\u0000-\u007F])(?:(?:[a-zA-Z0-9-]|[^\u0000-\u007F]){0,61}(?:[a-zA-Z0-9]|[^\u0000-\u007F]))?)+)*$/.test(t)}return!0}checkJson(e,t,r){try{JSON.parse(t)}catch(e){return!1}return!0}checkHexColor(e,t,r){return/^#(?:(?:[0-9a-f]{3}){1,2}|(?:[0-9a-f]{4}){1,2})$/i.test(t)}checkMacAddress(e,t,r){t=String(t);const s={"-":2,":":2,".":4};let i,c;for([i,c]of Object.entries(s))if(t.includes(i))break;const a=t.split(i);if(a.length!==12/c)return!1;for(const e of a)if(!new RegExp("^[0-9a-f]{"+c+"}$","i").test(e))return!1;return!0}checkIpv4(e,t,r){if(/[^\d.]/.test(t))return!1;const s=String(t).split(".");if(4!==s.length)return!1;for(const e of s)if(e<0||e>255)return!1;return!0}checkIpv6(e,t,r){if((t=String(t)).includes(":::")||t.split("::").length>2)return!1;const s=t.split(":");if(s.length<3||s.length>8)return!1;for(const e of s)if(""!==e&&!/^[0-9a-f]{1,4}$/i.test(e))return!1;return!0}checkIp(e,t,r){return this.checkIpv4(e,t,r)||this.checkIpv6(e,t,r)}checkTimezone(e,t,r){try{Intl.DateTimeFormat(void 0,{timeZone:t})}catch(e){if(String(e).toLowerCase().includes("invalid time zone"))return!1}return!0}checkUrl(e,t,r){try{new URL(t)}catch(e){return!1}return!0}checkUlid(e,t,r){return/[0-7][0-9A-HJKMNP-TV-Z]{25}/.test(t)}checkUuid(e,t,r){return/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/.test(t)}}class d{#r;keys(){return Object.keys(this.#r)}values(){return Object.values(this.#r)}entries(){return Object.entries(this.#r)}add(e,t){Object.hasOwn(this.#r,e)?this.#r[e].push(t):this.#r[e]=[t]}get(e){if(!e.includes("*"))return Object.hasOwn(this.#r,e)?this.#r[e]:{};const t=new RegExp("^"+e.replaceAll("*",".*?")+"$"),r={};for(const[e,s]of this.entries())t.test(e)&&(r[e]=s);return r}first(e){for(const t of Object.values(this.get(e)))return Array.isArray(t)?t[0]:t;return""}has(e){return""!==this.first(e)}remove(e){delete this.#r[e]}messages(){return this.#r}all(){const e=[];return this.values().forEach((t=>e.push(...t))),e}count(){let e=0;return this.values().forEach((t=>e+=t.length)),e}isEmpty(){return 0===this.keys().length}isNotEmpty(){return!this.isEmpty()}sortByKeys(e){const t={};for(const r of e)Object.hasOwn(this.#r,r)&&(t[r]=this.#r[r]);this.#r=t}constructor(){this.#r={}}}class p{static#s;static#i={};static locale(e){this.#s=e}static setMessages(e,t){this.#i[e]=s(t)}static get(e){if(this.#i[this.#s]&&this.#i[this.#s][e])return this.#i[this.#s][e]}static has(e){return void 0!==this.get(e)}static set(e,t){h(t)?Object.assign(this.#i[this.#s],s(t,e)):"string"==typeof t&&(this.#i[this.#s][e]=t)}}class f{constructor(e){this.validator=e}replace(e,t){return Object.entries(t).forEach((([t,r])=>e=e.replaceAll(":"+t,r))),e}replaceDecimal(e,t,r,s){return this.replace(e,{decimal:s.join("-")})}replaceMultipleOf(e,t,r,s){return this.replace(e,{value:s[0]})}replaceAcceptedIf(e,t,r,s){return this.replace(e,{other:this.validator.getDisplayableAttribute(s[0]),value:this.validator.getDisplayableValue(s[0],this.validator.getValue(s[0]))})}replaceDeclinedIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredArrayKeys(e,t,r,s){return this.replace(e,{values:s.map((e=>this.validator.getDisplayableValue(t,e))).join(", ")})}replaceRequiredIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredIfAccepted(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredIfDeclined(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredUnless(e,t,r,s){return this.replace(e,{other:this.validator.getDisplayableAttribute(s[0]),values:s.slice(1).map((e=>this.validator.getDisplayableValue(s[0],e))).join(", ")})}replaceRequiredWith(e,t,r,s){return this.replace(e,{values:s.map((e=>this.validator.getDisplayableAttribute(e))).join(" / ")})}replaceRequiredWithAll(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceRequiredWithout(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceRequiredWithoutAll(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceMissingIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceMissingUnless(e,t,r,s){return this.replace(this.replaceRequiredUnless(e,t,r,s),{value:this.validator.getDisplayableValue(s[0],s[1])})}replaceMissingWith(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceMissingWithAll(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceProhibitedIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceProhibitedUnless(e,t,r,s){return this.replaceRequiredUnless(e,t,r,s)}replaceProhibits(e,t,r,s){return this.replace(e,{other:s.map((e=>this.validator.getDisplayableAttribute(e))).join(" / ")})}replaceSize(e,t,r,s){return this.replace(e,{size:s[0]})}replaceMin(e,t,r,s){return this.replace(e,{min:s[0]})}replaceMax(e,t,r,s){return this.replace(e,{max:s[0]})}replaceBetween(e,t,r,s){return this.replace(e,{min:s[0],max:s[1]})}replaceDigits(e,t,r,s){return this.replace(e,{digits:s[0]})}replaceMinDigits(e,t,r,s){return this.replaceMin(e,t,r,s)}replaceMaxDigits(e,t,r,s){return this.replaceMax(e,t,r,s)}replaceDigitsBetween(e,t,r,s){return this.replaceBetween(e,t,r,s)}replaceStartsWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceDoesntStartWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceEndsWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceDoesntEndWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceSame(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceDifferent(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceGt(e,t,r,s){const i=this.validator.getValue(s[0]);return this.replace(e,{value:i?this.validator.getSize(s[0],i):this.validator.getDisplayableAttribute(s[0])})}replaceGte(e,t,r,s){return this.replaceGt(e,t,r,s)}replaceLt(e,t,r,s){return this.replaceGt(e,t,r,s)}replaceLte(e,t,r,s){return this.replaceGt(e,t,r,s)}replaceAfter(e,t,r,s){const i=s[0];return this.replace(e,{date:this.validator.hasAttribute(i)?this.validator.getDisplayableAttribute(i):i})}replaceAfterOrEqual(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceBefore(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceBeforeOrEqual(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceDateEquals(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceDateFormat(e,t,r,s){return this.replace(e,{format:s[0]})}replaceInArray(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceIn(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceNotIn(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceMimetypes(e,t,r,s){return this.replace(e,{values:s.join(", ")})}replaceMimes(e,t,r,s){return this.replaceMimetypes(e,t,r,s)}replaceExtensions(e,t,r,s){return this.replaceMimetypes(e,t,r,s)}}class g{static#c={};static#a={};static#n=["active_url","bail","can","current_password","enum","exclude","exclude_if","exclude_unless","exclude_with","exclude_without","exists","nullable","sometimes","unique"];static#u=["accepted","accepted_if","declined","declined_if","filled","missing","missing_if","missing_unless","missing_with","missing_with_all","present","required","required_if","required_if_accepted","required_if_declined","required_unless","required_with","required_with_all","required_without","required_without_all"];#r;#h;#l;#o;#d;#p;#f;#g;#m;#k;#b;#A;static setLocale(e){p.locale(e)}static setMessages(e,t){p.setMessages(e,t)}static addChecker(e,t,r){g.#c[e]=t,r&&p.set(e,r)}static addImplicitChecker(e,t,r){g.addChecker(e,t,r),g.#u.push(e)}static addReplacer(e,t){g.#a[e]=t}static addDummyRule(e){g.#n.push(e)}constructor(e={},r={},s={},i={},c={}){this.#m=[],this.#k={},this.#b=!1,this.#A=!1,this.fileRules=["file","image","mimetypes","mimes"],this.numericRules=["decimal","numeric","integer"],this.sizeRules=["size","between","min","max","gt","lt","gte","lte"],this.setProperties(e,r,s,i,c),this.#p=new o(this),this.#f=new f(this);for(const[e,r]of Object.entries(g.#c))this.#p[t("check_"+e)]=r;for(const[e,r]of Object.entries(g.#a))this.#f[t("replace_"+e)]=r;this.#g=new d}setProperties(e={},t={},r={},i={},c={}){return this.#r=e,this.#h=this.parseRules(t),this.#l=r,this.#o=i,this.#d=s(c),this}setData(e){return this.#r=e,this}setRules(e){return this.#h=this.parseRules(e),this}setCustomMessages(e){return this.#l=e,this}setCustomAttributes(e){return this.#o=e,this}setCustomValues(e){return this.#d=s(e),this}addImplicitAttribute(e,t){return this.#k[e]=t,this}stopOnFirstFailure(e=!0){return this.#b=e,this}alwaysBail(e=!0){return this.#A=e,this}parseRules(e){const t={};for(const[r,s]of Object.entries(e)){const e=r.includes("*")?this.parseWildcardAttribute(r):[r];for(const r of e){const e={};for(const t of this.parseAttributeRules(s)){const[r,s]=this.parseAttributeRule(t);e[r]=s}t[r]=e}}return t}parseWildcardAttribute(e){const t=[],r=e.indexOf("*"),s=e.substring(0,r-1),i=e.substring(r+2),c=this.getValue(s);return Array.isArray(c)||h(c)?(Object.entries(c).forEach((([r,c])=>{const a=`${s}.${r}.${i}`.replace(/\.$/,""),n=a.includes("*")?this.parseWildcardAttribute(a):[a];t.push(...n),n.forEach((t=>this.#k[t]=e))})),t):[e]}parseAttributeRules(e){return Array.isArray(e)?e:String(e).split("|")}parseAttributeRule(e){if(Array.isArray(e))return[e.shift()??"",e];const t=e.indexOf(":");return-1===t?[e,[]]:[e.substring(0,t),i(e.substring(t+1))]}async validate(){this.#p.clearCaches(),this.#g=new d;const e=[],r=[];for(const[s,i]of Object.entries(this.#h)){let c=this.getValue(s);Object.hasOwn(i,"sometimes")&&void 0===c?r.push(s):e.push((async()=>{const e=this.#A||Object.hasOwn(i,"bail"),a=Object.hasOwn(i,"nullable");let u=!0;for(const[h,l]of Object.entries(i)){if(""===h||!g.#u.includes(h)&&(void 0===c||"string"==typeof c&&""===c.trim()||a&&null===c)){r.push(s);continue}let i,o,d;const p=t("check_"+h);if("function"==typeof this.#p[p])i=await this.#p[p](s,c,l);else{if(!g.#n.includes(h))throw new Error(`Invalid validation rule: ${h}`);i=!0}if("boolean"==typeof i?o=i:({success:o,message:d}=i),!o&&(u=!1,d=n(d)?this.getMessage(s,h):d,d=this.makeReplacements(d,s,h,l),this.#g.add(s,d),e||g.#u.includes(h)))break}return u}))}if(this.#b){for(const t of e)if(!await t())break}else await Promise.allSettled(e.map((e=>e()))),this.#g.sortByKeys(Object.keys(this.#h));return this.#m=r.filter(((e,t,r)=>r.indexOf(e)===t)),this.#g}async passes(){return await this.validate(),!this.#g.isNotEmpty()}async fails(){return!await this.passes()}getMessage(e,t){const r=this.getValue(e);let s;e=this.getPrimaryAttribute(e);for(const r of[`${e}.${t}`,t])if(Object.hasOwn(this.#l,r)){s=this.#l[r];break}if(!s){let i=t;this.sizeRules.includes(i)&&(Array.isArray(r)||h(r)||this.hasRule(e,"array")?i+=".array":r instanceof File||this.hasRule(e,this.fileRules)?i+=".file":u(r)||this.hasRule(e,this.numericRules)?i+=".numeric":i+=".string"),s=p.get(i)}return s??`validation.${t}`}makeReplacements(e,r,s,i){const c=this.getDisplayableAttribute(r),a=this.getValue(r),n={attribute:c,ATTRIBUTE:c.toLocaleUpperCase(),Attribute:c.charAt(0).toLocaleUpperCase()+c.substring(1),input:this.getDisplayableValue(r,a)};for(const[t,r]of Object.entries(n))e=e.replaceAll(":"+t,r);const u=r.match(/\.(\d+)\.?/),h=null===u?-1:parseInt(u[1],10);-1!==h&&(e=e.replaceAll(":index",h).replaceAll(":position",h+1));const l=t("replace_"+s);return"function"==typeof this.#f[l]&&(e=this.#f[l](e,r,s,i)),e}getDisplayableAttribute(e){const t=this.getPrimaryAttribute(e);for(const r of[e,t]){if(Object.hasOwn(this.#o,r))return this.#o[r];if(p.has(`attributes.${r}`))return p.get(`attributes.${r}`)}return Object.hasOwn(this.#k,e)?e:(r=e,r.replace(/(.)(?=[A-Z])/g,(e=>e+"_")).toLowerCase()).replaceAll("_"," ");var r}getDisplayableValue(e,t){const r=`${e=this.getPrimaryAttribute(e)}.${t}`;return n(t)?"empty":"boolean"==typeof t||this.hasRule(e,"boolean")?Number(t)?"true":"false":Object.hasOwn(this.#d,r)?this.#d[r]:p.has(`values.${r}`)?p.get(`values.${r}`):t}getSize(e,t){return n(t)?0:u(t)&&this.hasRule(e,this.numericRules)?parseFloat("string"==typeof t?t.trim():t,10):t instanceof File?t.size/1024:h(t)?Object.keys(t).length:Object.hasOwn(t,"length")?t.length:t}getRule(e){return e=this.getPrimaryAttribute(e),this.#h[e]??{}}hasRule(e,t){if(e=this.getPrimaryAttribute(e),t="string"==typeof t?[t]:t,!Object.hasOwn(this.#h,e))return!1;for(const r of t)if(this.#h[e].hasOwnProperty(r))return!0;return!1}getPrimaryAttribute(e){return Object.hasOwn(this.#k,e)?this.#k[e]:e}hasAttribute(e){return void 0!==this.getValue(e)}getValue(e){return function(e,t,r){const s=t.split(".");let i=e;for(const e of s){if(!Object.hasOwn(i,e))return r;i=i[e]}return i}(this.#r,e)}errors(){return this.#g}skippedAttributes(){return this.#m}}return e.Checkers=o,e.ErrorBag=d,e.Lang=p,e.Replacers=f,e.Validator=g,e}({});
6
+ var quival=function(e){"use strict";function t(e){return e.replace(/[-_]/g," ").replace(/\s+/," ").trim().replace(/(\s\w)/g,(e=>e[1].toUpperCase()))}function r(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function s(e,t=""){return Object.keys(e).reduce(((r,i)=>{const c=t?`${t}.${i}`:i;return"object"==typeof e[i]&&null!==e[i]?Object.assign(r,s(e[i],c)):r[c]=e[i],r}),{})}function i(e){const t=[];let r="",s=!1;for(let i=0;i<e.length;i++){const c=e[i];'"'===c?s&&'"'===e[i+1]?(r+='"',i++):(s=!s,s&&(r=r.trim())):","!==c||s?r+=c:(t.push(r),r="")}return t.push(r),t}function c(e){if(n(e)||"string"!=typeof e)return new Date("");if(e instanceof Date)return e;let t,r,s,i,c,a,u,l;const h=e=>e&&/^\d*$/.test(e)?parseInt(e):e;if(null!==(t=e.match(/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{2,4})\s?((\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?)?/i)))[,i,s,r,,c=0,a=0,,u=0,l="am"]=t.map(h);else if(null!==(t=e.match(/^(\d{2,4})[.\/-](\d{1,2})[.\/-](\d{1,2})\s?((\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?)?/i))||null!==(t=e.match(/^(\d{4})(\d{2})(\d{2})\s?((\d{2})(\d{2})((\d{2}))?\s?(am|pm)?)?/i)))[,r,s,i,,c=0,a=0,,u=0,l="am"]=t.map(h);else if(t=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{4})[.\/-](\d{2})[.\/-](\d{2})/i))[,c,a,,u,l="am",r,s,i]=t.map(h);else if(t=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{2})[.\/-](\d{2})[.\/-](\d{4})/i))[,c,a,,u,l="am",i,s,r]=t.map(h);else{if(!(t=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?/i)))return new Date(e);{const e=new Date;r=e.getFullYear(),s=e.getMonth()+1,i=e.getDate(),[,c=0,a=0,,u=0,l="am"]=t.map(h)}}return r>=10&&r<100&&(r+=2e3),"pm"===l.toLowerCase()&&c<12&&(c+=12),new Date(`${r}-${s}-${i} ${c}:${a}:${u}`)}function a(e,t){if(n(e))return new Date("");t=t.split("");const r={Y:"(\\d{4})",y:"(\\d{2})",m:"(\\d{2})",n:"([1-9]\\d?)",d:"(\\d{2})",j:"([1-9]\\d?)",G:"([1-9]\\d?)",g:"([1-9]\\d?)",H:"(\\d{2})",h:"(\\d{2})",i:"(\\d{2})",s:"(\\d{2})",A:"(AM|PM)",a:"(am|pm)"};let s="^",i={years:-1,months:-1,days:-1,hours:-1,minutes:-1,seconds:-1,meridiem:-1},c=1;for(const e of t)Object.hasOwn(r,e)?(s+=r[e],-1!==["Y","y"].indexOf(e)?i.years=c++:-1!==["m","n"].indexOf(e)?i.months=c++:-1!==["d","j"].indexOf(e)?i.days=c++:-1!==["G","g","H","h"].indexOf(e)?i.hours=c++:"i"===e?i.minutes=c++:"s"===e?i.seconds=c++:-1!==["A","a"].indexOf(e)&&(i.meridiem=c++)):s+="\\"+e;s+="$";let a=e.match(new RegExp(s));if(null===a)return new Date("");a=a.map((e=>e&&/^\d*$/.test(e)?parseInt(e):e));const u=new Date;let l=a[i.years],h=a[i.months],o=a[i.days],d=a[i.hours]??0,p=a[i.minutes]??0,f=a[i.seconds]??0,g=a[i.meridiem]??"am";return l||h||o?!l||h||o?l||!h||o?l||h||!o||(l=u.getFullYear(),h=u.getMonth()+1):(l=u.getFullYear(),o=1):(h=1,o=1):(l=u.getFullYear(),h=u.getMonth()+1,o=u.getDate()),l>=10&&l<100&&(l+=2e3),"pm"===g.toLowerCase()&&d<12&&(d+=12),new Date(`${l}-${h}-${o} ${d}:${p}:${f}`)}function n(e){return""===e||null==e}function u(e){const t=Number(e);return null!==e&&"boolean"!=typeof e&&"number"==typeof t&&!isNaN(t)}function l(e){return"[object Object]"===Object.prototype.toString.call(e)}function h(e){return e instanceof Date&&"Invalid Date"!==e.toDateString()}class o{#e;#t;constructor(e){this.#e={},this.#t={},this.validator=e}clearCaches(){this.#e={},this.#t={}}isDependent(e){const t=this.validator.getValue(e[0]);return e.slice(1).some((e=>e==t))}collectRequiredsThenTest(e,t,r,s){let i=[];for(const e of r)i.push(this.checkRequired(e,this.validator.getValue(e)));return!s(i)||this.checkRequired(e,t)}collectMissingsThenTest(e,t,r,s){let i=[];for(const e of r)i.push(this.checkMissing(e));return!s(i)||this.checkMissing(e)}testStringUsingRegex(e,t,r,s,i=!1){return("string"==typeof t||"number"==typeof t)&&(t=String(t),i||this.validator.hasRule(e,"ascii")?r.test(t):s.test(t))}compareValues(e,t,r,s){if(n(t))return!1;const i=r[0]??"";let c=this.validator.getValue(i);return c=void 0===c?u(i)?parseFloat(i,10):null:this.validator.getSize(i,c),!n(c)&&s(this.validator.getSize(e,t),c)}compareDates(e,t,r,s){const i=this.validator.getRule(e);if(!h(t=Object.hasOwn(i,"date_format")?a(t,i.date_format[0]):c(t)))return!1;const n=r[0]??"";let u=this.validator.getValue(n);if(void 0===u)u=c(n);else{const e=this.validator.getRule(n);u=Object.hasOwn(e,"date_format")?a(u,e.date_format[0]):c(u)}return!!h(u)&&s(t.getTime(),u.getTime())}checkArray(e,t,r){if(!Array.isArray(t)&&!l(t))return!1;if(r&&r.length>0)for(const e of Object.keys(t))if(!r.includes(e))return!1;return!0}checkList(e,t,r){return Array.isArray(t)}checkBoolean(e,t,r){return[!0,!1,0,1,"0","1"].includes(t)}checkDate(e,t,r){return h(c(t))}checkFile(e,t,r){return t instanceof File}checkInteger(e,t,r){return String(parseInt(t,10))===String(t)}checkNumeric(e,t,r){return u(t)}checkString(e,t,r){return"string"==typeof t}checkDecimal(e,t,r){if(!this.checkNumeric(e,t))return!1;const s=(String(t).split(".")[1]??"").length;return 1===r.length?s==r[0]:s>=r[0]&&s<=r[1]}checkMultipleOf(e,t,r){if(!u(t)||!u(r[0]))return!1;const s=parseInt(t,10),i=parseInt(r[0],10);return(0!==s||0!==i)&&(0===s||0!==i&&s%i==0)}checkAccepted(e,t,r){return["yes","on","1",1,!0,"true"].includes(t)}checkAcceptedIf(e,t,r){return!this.isDependent(r)||this.checkAccepted(e,t,r)}checkDeclined(e,t,r){return["no","off","0",0,!1,"false"].includes(t)}checkDeclinedIf(e,t,r){return!this.isDependent(r)||this.checkDeclined(e,t,r)}checkRequired(e,t,r){return!n(t)&&(Array.isArray(t)?t.length>0:t instanceof File?t.size>0:(t=String(t).replace(/\s/g,"")).length>0)}checkRequiredArrayKeys(e,t,r){if(!this.checkArray(e,t))return!1;const s=Object.keys(t);for(const e of r)if(!s.includes(e))return!1;return!0}checkRequiredIf(e,t,r){return!this.isDependent(r)||this.checkRequired(e,t)}checkRequiredIfAccepted(e,t,r){return!this.checkAccepted(r[0],this.validator.getValue(r[0]))||this.checkRequired(e,t)}checkRequiredIfDeclined(e,t,r){return!this.checkDeclined(r[0],this.validator.getValue(r[0]))||this.checkRequired(e,t)}checkRequiredUnless(e,t,r){return!!this.isDependent(r)||this.checkRequired(e,t)}checkRequiredWith(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>e.includes(!0)))}checkRequiredWithAll(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>!e.includes(!1)))}checkRequiredWithout(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>e.includes(!1)))}checkRequiredWithoutAll(e,t,r){return this.collectRequiredsThenTest(e,t,r,(e=>!e.includes(!0)))}checkFilled(e,t,r){return void 0===t||this.checkRequired(e,t)}checkPresent(e,t,r){return void 0!==t}checkMissing(e,t,r){return!this.validator.hasAttribute(e)}checkMissingIf(e,t,r){return!this.isDependent(r)||this.checkMissing(e)}checkMissingUnless(e,t,r){return!!this.isDependent(r)||this.checkMissing(e)}checkMissingWith(e,t,r){return this.collectMissingsThenTest(e,t,r,(e=>e.includes(!1)))}checkMissingWithAll(e,t,r){return this.collectMissingsThenTest(e,t,r,(e=>!e.includes(!0)))}checkProhibited(e,t,r){return!this.checkRequired(e,t)}checkProhibitedIf(e,t,r){return!this.isDependent(r)||!this.checkRequired(e,t)}checkProhibitedUnless(e,t,r){return!!this.isDependent(r)||!this.checkRequired(e,t)}checkProhibits(e,t,r){if(this.checkRequired(e,t))for(const e of r)if(this.checkRequired(e,this.validator.getValue(e)))return!1;return!0}checkSize(e,t,r){return this.validator.getSize(e,t)===parseFloat(r[0])}checkMin(e,t,r){return this.validator.getSize(e,t)>=parseFloat(r[0])}checkMax(e,t,r){return this.validator.getSize(e,t)<=parseFloat(r[0])}checkBetween(e,t,r){return this.checkMin(e,t,[r[0]])&&this.checkMax(e,t,[r[1]])}checkDigits(e,t,r,s=(e,t)=>e===t){return!!function(e){return-1===String(e).search(/[^0-9]/)}(t=String(t??""))&&s(t.length,parseInt(r[0],10),parseInt(r[1]??0,10))}checkMinDigits(e,t,r){return this.checkDigits(e,t,r,((e,t)=>e>=t))}checkMaxDigits(e,t,r){return this.checkDigits(e,t,r,((e,t)=>e<=t))}checkDigitsBetween(e,t,r){return this.checkDigits(e,t,r,((e,t,r)=>e>=t&&e<=r))}checkAlpha(e,t,r){return this.testStringUsingRegex(e,t,/^[a-z]+$/i,/^[\p{L}\p{M}]+$/u,r.includes("ascii"))}checkAlphaDash(e,t,r){return this.testStringUsingRegex(e,t,/^[a-z0-9_-]+$/i,/^[\p{L}\p{M}\p{N}_-]+$/u,r.includes("ascii"))}checkAlphaNum(e,t,r){return this.testStringUsingRegex(e,t,/^[a-z0-9]+$/i,/^[\p{L}\p{M}\p{N}]+$/u,r.includes("ascii"))}checkAscii(e,t,r){return!/[^\x09\x10\x13\x0A\x0D\x20-\x7E]/.test(t)}checkRegex(e,t,r,s=!1){if("string"!=typeof t&&!u(t))return!1;const i=r.join(",");let[c,a,l]=i.match(/^\/(.*)\/([gimu]*)$/)??[];if(n(c))throw new Error(`Invalid regular expression pattern: ${i}`);l.includes("u")&&(a=a.replace(/\\A/g,"^").replace(/\\z/gi,"$").replace(/\\([pP])([CLMNPSZ])/g,"\\$1{$2}").replace(/\\\x\{([0-9a-f]+)\}/g,"\\u{$1}"));const h=new RegExp(a,l).test(t);return s?!h:h}checkNotRegex(e,t,r){return this.checkRegex(e,t,r,!0)}checkLowercase(e,t,r){return t===String(t).toLocaleLowerCase()}checkUppercase(e,t,r){return t===String(t).toLocaleUpperCase()}checkStartsWith(e,t,r){t=String(t);for(const e of r)if(t.startsWith(e))return!0;return!1}checkDoesntStartWith(e,t,r){return!this.checkStartsWith(e,t,r)}checkEndsWith(e,t,r){t=String(t);for(const e of r)if(t.endsWith(e))return!0;return!1}checkDoesntEndWith(e,t,r){return!this.checkEndsWith(e,t,r)}checkSame(e,t,r){return t===this.validator.getValue(r[0])}checkDifferent(e,t,r){for(const e of r){const r=this.validator.getValue(e);if(void 0!==r&&t===r)return!1}return!0}checkConfirmed(e,t,r){return this.checkSame(e,t,[e+"_confirmation"])}checkGt(e,t,r){return this.compareValues(e,t,r,((e,t)=>e>t))}checkGte(e,t,r){return this.compareValues(e,t,r,((e,t)=>e>=t))}checkLt(e,t,r){return this.compareValues(e,t,r,((e,t)=>e<t))}checkLte(e,t,r){return this.compareValues(e,t,r,((e,t)=>e<=t))}checkAfter(e,t,r){return this.compareDates(e,t,r,((e,t)=>e>t))}checkAfterOrEqual(e,t,r){return this.compareDates(e,t,r,((e,t)=>e>=t))}checkBefore(e,t,r){return this.compareDates(e,t,r,((e,t)=>e<t))}checkBeforeOrEqual(e,t,r){return this.compareDates(e,t,r,((e,t)=>e<=t))}checkDateEquals(e,t,r){return this.compareDates(e,t,r,((e,t)=>e===t))}checkDateFormat(e,t,r){const s=r[0].split(""),i={Y:"(\\d{4})",y:"(\\d{2})",m:"(\\d{2})",n:"([1-9]\\d?)",d:"(\\d{2})",j:"([1-9]\\d?)",G:"([1-9]\\d?)",g:"([1-9]\\d?)",H:"(\\d{2})",h:"(\\d{2})",i:"(\\d{2})",s:"(\\d{2})",A:"(AM|PM)",a:"(am|pm)"};let c="^";for(const e of s)Object.hasOwn(i,e)?c+=i[e]:c+="\\"+e;return c+="$",new RegExp(c).test(t)}checkContains(e,t,r){if(!this.checkArray(e,t))return!1;for(const e of r)if(!t.includes(e))return!1;return!0}checkDistinct(e,t,i){const c=this.validator.getPrimaryAttribute(e);if(!c.includes("*"))return!0;const a=c.indexOf("*"),n=c.substring(0,a-1);let u;Object.hasOwn(this.#e,n)?u=this.#e[n]:(u=JSON.stringify(s(this.validator.getValue(n)??{})),this.#e[n]=u);const l=i.includes("ignore_case"),h=!l&&i.includes("strict"),o=r(String(t));let d=`"${r(c.substring(a)).replaceAll("\\*",'[^."]+')}":`,p=0;return d+=h?"string"==typeof t?`"${o}"`:`${o}`:`(${o}|"${o}")`,d+="[,}]+",p+=u.match(new RegExp(d,"g"+(l?"i":"")))?.length??0,1===p}checkInArray(e,t,r){const i=this.validator.getPrimaryAttribute(r[0]);if(!i.includes("*"))return!1;const c=this.validator.getValue(i.split(".*")[0])??{};return Object.values(s(c)).some((e=>e==t))}checkIn(e,t,r){if(!this.checkArray(e,t)||!this.validator.hasRule(e,"array"))return r.some((e=>e==t));for(const e of Object.values(t))if(!r.some((t=>t==e)))return!1;return!0}checkNotIn(e,t,r){return!this.checkIn(e,t,r)}checkMimetypes(e,t,r){return!!this.checkFile(e,t)&&r.includes(t.type)}checkMimes(e,t,r){return!!this.checkFile(e,t)&&(r.includes("jpg")&&!r.includes("jpeg")&&r.push("jpeg"),r.includes("jpeg")&&!r.includes("jpg")&&r.push("jpg"),r.includes(t.name.split(".").pop().toLowerCase()))}checkExtensions(e,t,r){return this.checkMimes(e,t,r)}async checkImage(e,t,r){let s=this.checkMimes(e,t,["jpg","jpeg","png","gif","bmp","svg","webp"]);return s&&"undefined"!=typeof FileReader?(await new Promise(((e,r)=>{const s=new FileReader;s.onload=t=>e(t.target.result),s.onerror=r,s.readAsDataURL(t)})).then((async t=>{const r=new Image;r.src=t,await r.decode(),this.#t[e]=r})).catch((()=>{s=!1})),s):s}async checkDimensions(e,t,r){if(!this.checkImage(e,t)||!Object.hasOwn(this.#t,e))return!1;const s={};for(const e of r){const[t,r]=e.split("=",2);if("ratio"===t&&r.includes("/")){const[e,i]=r.split("/",2).map((e=>parseFloat(e,10)));s[t]=e/i}else s[t]=parseFloat(r,10)}const i=this.#t[e],c=i.naturalWidth,a=i.naturalHeight;return!(Object.hasOwn(s,"width")&&s.width!==c||Object.hasOwn(s,"height")&&s.height!==a||Object.hasOwn(s,"min_width")&&s.min_width>c||Object.hasOwn(s,"min_height")&&s.min_height>a||Object.hasOwn(s,"max_width")&&s.max_width<c||Object.hasOwn(s,"max_height")&&s.max_height<a)&&(!Object.hasOwn(s,"ratio")||Math.abs(s.ratio-c/a)<=1/(Math.max(c,a)+1))}checkEmail(e,t,r){if(!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(t)){return/^((?:[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]|[^\u0000-\u007F])+@(?:[a-zA-Z0-9]|[^\u0000-\u007F])(?:(?:[a-zA-Z0-9-]|[^\u0000-\u007F]){0,61}(?:[a-zA-Z0-9]|[^\u0000-\u007F]))?(?:\.(?:[a-zA-Z0-9]|[^\u0000-\u007F])(?:(?:[a-zA-Z0-9-]|[^\u0000-\u007F]){0,61}(?:[a-zA-Z0-9]|[^\u0000-\u007F]))?)+)*$/.test(t)}return!0}checkJson(e,t,r){try{JSON.parse(t)}catch(e){return!1}return!0}checkHexColor(e,t,r){return/^#(?:(?:[0-9a-f]{3}){1,2}|(?:[0-9a-f]{4}){1,2})$/i.test(t)}checkMacAddress(e,t,r){t=String(t);const s={"-":2,":":2,".":4};let i,c;for([i,c]of Object.entries(s))if(t.includes(i))break;const a=t.split(i);if(a.length!==12/c)return!1;for(const e of a)if(!new RegExp("^[0-9a-f]{"+c+"}$","i").test(e))return!1;return!0}checkIpv4(e,t,r){if(/[^\d.]/.test(t))return!1;const s=String(t).split(".");if(4!==s.length)return!1;for(const e of s)if(e<0||e>255)return!1;return!0}checkIpv6(e,t,r){if((t=String(t)).includes(":::")||t.split("::").length>2)return!1;const s=t.split(":");if(s.length<3||s.length>8)return!1;for(const e of s)if(""!==e&&!/^[0-9a-f]{1,4}$/i.test(e))return!1;return!0}checkIp(e,t,r){return this.checkIpv4(e,t,r)||this.checkIpv6(e,t,r)}checkTimezone(e,t,r){try{Intl.DateTimeFormat(void 0,{timeZone:t})}catch(e){if(String(e).toLowerCase().includes("invalid time zone"))return!1}return!0}checkUrl(e,t,r){try{new URL(t)}catch(e){return!1}return!0}checkUlid(e,t,r){return/[0-7][0-9A-HJKMNP-TV-Z]{25}/.test(t)}checkUuid(e,t,r){return/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/.test(t)}}class d{#r;keys(){return Object.keys(this.#r)}values(){return Object.values(this.#r)}entries(){return Object.entries(this.#r)}add(e,t){Object.hasOwn(this.#r,e)?this.#r[e].push(t):this.#r[e]=[t]}get(e){if(!e.includes("*"))return Object.hasOwn(this.#r,e)?this.#r[e]:{};const t=new RegExp("^"+e.replaceAll("*",".*?")+"$"),r={};for(const[e,s]of this.entries())t.test(e)&&(r[e]=s);return r}first(e){for(const t of Object.values(this.get(e)))return Array.isArray(t)?t[0]:t;return""}has(e){return""!==this.first(e)}remove(e){delete this.#r[e]}messages(){return this.#r}all(){const e=[];return this.values().forEach((t=>e.push(...t))),e}count(){let e=0;return this.values().forEach((t=>e+=t.length)),e}isEmpty(){return 0===this.keys().length}isNotEmpty(){return!this.isEmpty()}sortByKeys(e){const t={};for(const r of e)Object.hasOwn(this.#r,r)&&(t[r]=this.#r[r]);this.#r=t}constructor(){this.#r={}}}class p{static#s;static#i={};static locale(e){this.#s=e}static setMessages(e,t){this.#i[e]=s(t)}static get(e){if(this.#i[this.#s]&&this.#i[this.#s][e])return this.#i[this.#s][e]}static has(e){return void 0!==this.get(e)}static set(e,t){l(t)?Object.assign(this.#i[this.#s],s(t,e)):"string"==typeof t&&(this.#i[this.#s][e]=t)}}class f{constructor(e){this.validator=e}replace(e,t){return Object.entries(t).forEach((([t,r])=>e=e.replaceAll(":"+t,r))),e}replaceDecimal(e,t,r,s){return this.replace(e,{decimal:s.join("-")})}replaceMultipleOf(e,t,r,s){return this.replace(e,{value:s[0]})}replaceAcceptedIf(e,t,r,s){return this.replace(e,{other:this.validator.getDisplayableAttribute(s[0]),value:this.validator.getDisplayableValue(s[0],this.validator.getValue(s[0]))})}replaceDeclinedIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredArrayKeys(e,t,r,s){return this.replace(e,{values:s.map((e=>this.validator.getDisplayableValue(t,e))).join(", ")})}replaceRequiredIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredIfAccepted(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredIfDeclined(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceRequiredUnless(e,t,r,s){return this.replace(e,{other:this.validator.getDisplayableAttribute(s[0]),values:s.slice(1).map((e=>this.validator.getDisplayableValue(s[0],e))).join(", ")})}replaceRequiredWith(e,t,r,s){return this.replace(e,{values:s.map((e=>this.validator.getDisplayableAttribute(e))).join(" / ")})}replaceRequiredWithAll(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceRequiredWithout(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceRequiredWithoutAll(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceMissingIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceMissingUnless(e,t,r,s){return this.replace(this.replaceRequiredUnless(e,t,r,s),{value:this.validator.getDisplayableValue(s[0],s[1])})}replaceMissingWith(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceMissingWithAll(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replaceProhibitedIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceProhibitedUnless(e,t,r,s){return this.replaceRequiredUnless(e,t,r,s)}replaceProhibits(e,t,r,s){return this.replace(e,{other:s.map((e=>this.validator.getDisplayableAttribute(e))).join(" / ")})}replaceSize(e,t,r,s){return this.replace(e,{size:s[0]})}replaceMin(e,t,r,s){return this.replace(e,{min:s[0]})}replaceMax(e,t,r,s){return this.replace(e,{max:s[0]})}replaceBetween(e,t,r,s){return this.replace(e,{min:s[0],max:s[1]})}replaceDigits(e,t,r,s){return this.replace(e,{digits:s[0]})}replaceMinDigits(e,t,r,s){return this.replaceMin(e,t,r,s)}replaceMaxDigits(e,t,r,s){return this.replaceMax(e,t,r,s)}replaceDigitsBetween(e,t,r,s){return this.replaceBetween(e,t,r,s)}replaceStartsWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceDoesntStartWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceEndsWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceDoesntEndWith(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceSame(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceDifferent(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceGt(e,t,r,s){const i=this.validator.getValue(s[0]);return this.replace(e,{value:i?this.validator.getSize(s[0],i):this.validator.getDisplayableAttribute(s[0])})}replaceGte(e,t,r,s){return this.replaceGt(e,t,r,s)}replaceLt(e,t,r,s){return this.replaceGt(e,t,r,s)}replaceLte(e,t,r,s){return this.replaceGt(e,t,r,s)}replaceAfter(e,t,r,s){const i=s[0];return this.replace(e,{date:this.validator.hasAttribute(i)?this.validator.getDisplayableAttribute(i):i})}replaceAfterOrEqual(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceBefore(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceBeforeOrEqual(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceDateEquals(e,t,r,s){return this.replaceAfter(e,t,r,s)}replaceDateFormat(e,t,r,s){return this.replace(e,{format:s[0]})}replaceInArray(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replaceIn(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceNotIn(e,t,r,s){return this.replaceRequiredArrayKeys(e,t,r,s)}replaceMimetypes(e,t,r,s){return this.replace(e,{values:s.join(", ")})}replaceMimes(e,t,r,s){return this.replaceMimetypes(e,t,r,s)}replaceExtensions(e,t,r,s){return this.replaceMimetypes(e,t,r,s)}}class g{static#c={};static#a={};static#n=["active_url","bail","can","current_password","enum","exclude","exclude_if","exclude_unless","exclude_with","exclude_without","exists","nullable","sometimes","unique"];static#u=["accepted","accepted_if","declined","declined_if","filled","missing","missing_if","missing_unless","missing_with","missing_with_all","present","required","required_if","required_if_accepted","required_if_declined","required_unless","required_with","required_with_all","required_without","required_without_all"];#r;#l;#h;#o;#d;#p;#f;#g;#m;#k;#b;#A;static setLocale(e){p.locale(e)}static setMessages(e,t){p.setMessages(e,t)}static addChecker(e,t,r){g.#c[e]=t,r&&p.set(e,r)}static addImplicitChecker(e,t,r){g.addChecker(e,t,r),g.#u.push(e)}static addReplacer(e,t){g.#a[e]=t}static addDummyRule(e){g.#n.push(e)}constructor(e={},r={},s={},i={},c={}){this.#m=[],this.#k={},this.#b=!1,this.#A=!1,this.fileRules=["file","image","mimetypes","mimes"],this.numericRules=["decimal","numeric","integer"],this.sizeRules=["size","between","min","max","gt","lt","gte","lte"],this.setProperties(e,r,s,i,c),this.#p=new o(this),this.#f=new f(this);for(const[e,r]of Object.entries(g.#c))this.#p[t("check_"+e)]=r;for(const[e,r]of Object.entries(g.#a))this.#f[t("replace_"+e)]=r;this.#g=new d}setProperties(e={},t={},r={},i={},c={}){return this.#r=e,this.#l=this.parseRules(t),this.#h=r,this.#o=i,this.#d=s(c),this}setData(e){return this.#r=e,this}setRules(e){return this.#l=this.parseRules(e),this}setCustomMessages(e){return this.#h=e,this}setCustomAttributes(e){return this.#o=e,this}setCustomValues(e){return this.#d=s(e),this}addImplicitAttribute(e,t){return this.#k[e]=t,this}stopOnFirstFailure(e=!0){return this.#b=e,this}alwaysBail(e=!0){return this.#A=e,this}parseRules(e){const t={};for(const[r,s]of Object.entries(e)){const e=r.includes("*")?this.parseWildcardAttribute(r):[r];for(const r of e){const e=[];for(const t of this.parseAttributeRules(s))e.push(this.parseAttributeRule(t));t[r]=e}}return t}parseWildcardAttribute(e){const t=[],r=e.indexOf("*"),s=e.substring(0,r-1),i=e.substring(r+2),c=this.getValue(s);return Array.isArray(c)||l(c)?(Object.entries(c).forEach((([r,c])=>{const a=`${s}.${r}.${i}`.replace(/\.$/,""),n=a.includes("*")?this.parseWildcardAttribute(a):[a];t.push(...n),n.forEach((t=>this.#k[t]=e))})),t):[e]}parseAttributeRules(e){return Array.isArray(e)?e:"function"==typeof e?[e]:String(e).split("|")}parseAttributeRule(e){if(Array.isArray(e))return[e[0]??"",e.slice(1)];if("function"==typeof e)return[e,[]];const t=e.indexOf(":");return-1===t?[e,[]]:[e.substring(0,t),i(e.substring(t+1))]}async validate(){this.#p.clearCaches(),this.#g=new d;const e=[],r=[];for(const[e,r]of Object.entries(this.#l))for(const[e]of r)if(""!==e&&"function"!=typeof e&&"function"!=typeof this.#p[t("check_"+e)]&&!g.#n.includes(e))throw new Error(`Invalid validation rule: ${e}`);for(const[s,i]of Object.entries(this.#l)){let c=this.getValue(s);const a=e=>i.some((t=>t[0]===e));a("sometimes")&&void 0===c?r.push(s):e.push((async()=>{const e=this.#A||a("bail"),u=a("nullable");let l=!0;for(const[a,h]of i){if(""===a||"function"!=typeof a&&!g.#u.includes(a)&&(void 0===c||"string"==typeof c&&""===c.trim()||u&&null===c)){r.push(s);continue}let i,o,d;const p=(()=>{if("function"==typeof a)return a;{const e=this.#p[t("check_"+a)]??null;return null===e&&g.#n.includes(a)?()=>!0:e}})();if(null===p)throw new Error(`Invalid validation rule: ${a}`);if(i=await p.call(this.#p,s,c,h),"boolean"==typeof i&&(i={success:i}),({success:o,message:d=""}=i),!o&&(l=!1,d=n(d)?this.getMessage(s,a):d,d=this.makeReplacements(d,s,a,h),this.#g.add(s,d),e||g.#u.includes(a)))break}return l}))}if(this.#b){for(const t of e)if(!await t())break}else await Promise.allSettled(e.map((e=>e()))).then((e=>{for(const t of e)if("rejected"===t.status)throw t.reason})),this.#g.sortByKeys(Object.keys(this.#l));return this.#m=r.filter(((e,t,r)=>r.indexOf(e)===t)),this.#g}async passes(){return await this.validate(),!this.#g.isNotEmpty()}async fails(){return!await this.passes()}getMessage(e,t){if("function"==typeof t)return"";const r=this.getValue(e);let s;e=this.getPrimaryAttribute(e);for(const r of[`${e}.${t}`,t])if(Object.hasOwn(this.#h,r)){s=this.#h[r];break}if(!s){let i=t;this.sizeRules.includes(i)&&(Array.isArray(r)||l(r)||this.hasRule(e,"array")?i+=".array":r instanceof File||this.hasRule(e,this.fileRules)?i+=".file":u(r)||this.hasRule(e,this.numericRules)?i+=".numeric":i+=".string"),s=p.get(i)}return s??`validation.${t}`}makeReplacements(e,r,s,i){const c=this.getDisplayableAttribute(r),a=this.getValue(r),n={attribute:c,ATTRIBUTE:c.toLocaleUpperCase(),Attribute:c.charAt(0).toLocaleUpperCase()+c.substring(1),input:this.getDisplayableValue(r,a)};for(const[t,r]of Object.entries(n))e=e.replaceAll(":"+t,r);const u=r.match(/\.(\d+)\.?/),l=null===u?-1:parseInt(u[1],10);if(-1!==l&&(e=e.replaceAll(":index",l).replaceAll(":position",l+1)),"string"==typeof s){const c=this.#f[t("replace_"+s)]??null;c&&(e=c.call(this.#f,e,r,s,i))}return e}getDisplayableAttribute(e){const t=this.getPrimaryAttribute(e);for(const r of[e,t]){if(Object.hasOwn(this.#o,r))return this.#o[r];if(p.has(`attributes.${r}`))return p.get(`attributes.${r}`)}return Object.hasOwn(this.#k,e)?e:(r=e,r.replace(/(.)(?=[A-Z])/g,(e=>e+"_")).toLowerCase()).replaceAll("_"," ");var r}getDisplayableValue(e,t){const r=`${e=this.getPrimaryAttribute(e)}.${t}`;return n(t)?"empty":"boolean"==typeof t||this.hasRule(e,"boolean")?Number(t)?"true":"false":Object.hasOwn(this.#d,r)?this.#d[r]:p.has(`values.${r}`)?p.get(`values.${r}`):t}getSize(e,t){return n(t)?0:u(t)&&this.hasRule(e,this.numericRules)?parseFloat("string"==typeof t?t.trim():t,10):t instanceof File?t.size/1024:l(t)?Object.keys(t).length:Object.hasOwn(t,"length")?t.length:t}getRule(e){return e=this.getPrimaryAttribute(e),this.#l[e]??{}}hasRule(e,t){if(e=this.getPrimaryAttribute(e),t="string"==typeof t?[t]:t,!Object.hasOwn(this.#l,e))return!1;for(const r of t)if(this.#l[e].some((e=>e[0]===r)))return!0;return!1}getPrimaryAttribute(e){return Object.hasOwn(this.#k,e)?this.#k[e]:e}hasAttribute(e){return void 0!==this.getValue(e)}getValue(e){return function(e,t,r){const s=t.split(".");let i=e;for(const e of s){if(!Object.hasOwn(i,e))return r;i=i[e]}return i}(this.#r,e)}errors(){return this.#g}skippedAttributes(){return this.#m}}return e.Checkers=o,e.ErrorBag=d,e.Lang=p,e.Replacers=f,e.Validator=g,e}({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quival",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "Data validation à la Laravel Validation",
5
5
  "author": "Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>",
6
6
  "license": "MIT",
package/src/Validator.js CHANGED
@@ -178,12 +178,10 @@ export default class Validator {
178
178
  const attributes = attribute.includes('*') ? this.parseWildcardAttribute(attribute) : [attribute];
179
179
 
180
180
  for (const attribute of attributes) {
181
- const parsedAttributeRules = {};
181
+ const parsedAttributeRules = [];
182
182
 
183
183
  for (const attributeRule of this.parseAttributeRules(attributeRules)) {
184
- const [rule, parameters] = this.parseAttributeRule(attributeRule);
185
-
186
- parsedAttributeRules[rule] = parameters;
184
+ parsedAttributeRules.push(this.parseAttributeRule(attributeRule));
187
185
  }
188
186
 
189
187
  parsedRules[attribute] = parsedAttributeRules;
@@ -218,6 +216,8 @@ export default class Validator {
218
216
  parseAttributeRules(rules) {
219
217
  if (Array.isArray(rules)) {
220
218
  return rules;
219
+ } else if (typeof rules === 'function') {
220
+ return [rules];
221
221
  } else {
222
222
  return String(rules).split('|');
223
223
  }
@@ -225,7 +225,9 @@ export default class Validator {
225
225
 
226
226
  parseAttributeRule(rule) {
227
227
  if (Array.isArray(rule)) {
228
- return [rule.shift() ?? '', rule];
228
+ return [rule[0] ?? '', rule.slice(1)];
229
+ } else if (typeof rule === 'function') {
230
+ return [rule, []];
229
231
  }
230
232
 
231
233
  const index = rule.indexOf(':');
@@ -244,23 +246,39 @@ export default class Validator {
244
246
  const tasks = [];
245
247
  const skippedAttributes = [];
246
248
 
249
+ for (const [attribute, rules] of Object.entries(this.#rules)) {
250
+ for (const [rule] of rules) {
251
+ if (
252
+ rule === '' ||
253
+ typeof rule === 'function' ||
254
+ typeof this.#checkers[toCamelCase('check_' + rule)] === 'function' ||
255
+ Validator.#dummyRules.includes(rule)
256
+ )
257
+ continue;
258
+
259
+ throw new Error(`Invalid validation rule: ${rule}`);
260
+ }
261
+ }
262
+
247
263
  for (const [attribute, rules] of Object.entries(this.#rules)) {
248
264
  let value = this.getValue(attribute);
265
+ const hasRule = (ruleName) => rules.some((rule) => rule[0] === ruleName);
249
266
 
250
- if (Object.hasOwn(rules, 'sometimes') && typeof value === 'undefined') {
267
+ if (hasRule('sometimes') && typeof value === 'undefined') {
251
268
  skippedAttributes.push(attribute);
252
269
  continue;
253
270
  }
254
271
 
255
272
  tasks.push(async () => {
256
- const doBail = this.#alwaysBail || Object.hasOwn(rules, 'bail');
257
- const isNullable = Object.hasOwn(rules, 'nullable');
273
+ const doBail = this.#alwaysBail || hasRule('bail');
274
+ const isNullable = hasRule('nullable');
258
275
  let noError = true;
259
276
 
260
- for (const [rule, parameters] of Object.entries(rules)) {
277
+ for (const [rule, parameters] of rules) {
261
278
  if (
262
279
  rule === '' ||
263
- (!Validator.#implicitRules.includes(rule) &&
280
+ (typeof rule !== 'function' &&
281
+ !Validator.#implicitRules.includes(rule) &&
264
282
  (typeof value === 'undefined' || (typeof value === 'string' && value.trim() === '') || (isNullable && value === null)))
265
283
  ) {
266
284
  skippedAttributes.push(attribute);
@@ -268,22 +286,33 @@ export default class Validator {
268
286
  }
269
287
 
270
288
  let result, success, message;
271
- const camelRule = toCamelCase('check_' + rule);
272
289
 
273
- if (typeof this.#checkers[camelRule] === 'function') {
274
- result = await this.#checkers[camelRule](attribute, value, parameters);
275
- } else if (Validator.#dummyRules.includes(rule)) {
276
- result = true;
277
- } else {
290
+ const checker = (() => {
291
+ if (typeof rule === 'function') {
292
+ return rule;
293
+ } else {
294
+ const checker = this.#checkers[toCamelCase('check_' + rule)] ?? null;
295
+
296
+ if (checker === null && Validator.#dummyRules.includes(rule)) {
297
+ return () => true;
298
+ }
299
+
300
+ return checker;
301
+ }
302
+ })();
303
+
304
+ if (checker === null) {
278
305
  throw new Error(`Invalid validation rule: ${rule}`);
279
306
  }
280
307
 
308
+ result = await checker.call(this.#checkers, attribute, value, parameters);
309
+
281
310
  if (typeof result === 'boolean') {
282
- success = result;
283
- } else {
284
- ({ success, message } = result);
311
+ result = { success: result };
285
312
  }
286
313
 
314
+ ({ success, message = '' } = result);
315
+
287
316
  if (!success) {
288
317
  noError = false;
289
318
  message = isEmpty(message) ? this.getMessage(attribute, rule) : message;
@@ -306,7 +335,13 @@ export default class Validator {
306
335
  if (!(await task())) break;
307
336
  }
308
337
  } else {
309
- await Promise.allSettled(tasks.map((task) => task()));
338
+ await Promise.allSettled(tasks.map((task) => task())).then((results) => {
339
+ for (const result of results) {
340
+ if (result.status === 'rejected') {
341
+ throw result.reason;
342
+ }
343
+ }
344
+ });
310
345
 
311
346
  this.#errors.sortByKeys(Object.keys(this.#rules));
312
347
  }
@@ -331,6 +366,10 @@ export default class Validator {
331
366
  }
332
367
 
333
368
  getMessage(attribute, rule) {
369
+ if (typeof rule === 'function') {
370
+ return '';
371
+ }
372
+
334
373
  const value = this.getValue(attribute);
335
374
  attribute = this.getPrimaryAttribute(attribute);
336
375
 
@@ -387,10 +426,12 @@ export default class Validator {
387
426
  message = message.replaceAll(':index', index).replaceAll(':position', index + 1);
388
427
  }
389
428
 
390
- const camelRule = toCamelCase('replace_' + rule);
429
+ if (typeof rule === 'string') {
430
+ const replacer = this.#replacers[toCamelCase('replace_' + rule)] ?? null;
391
431
 
392
- if (typeof this.#replacers[camelRule] === 'function') {
393
- message = this.#replacers[camelRule](message, attribute, rule, parameters);
432
+ if (replacer) {
433
+ message = replacer.call(this.#replacers, message, attribute, rule, parameters);
434
+ }
394
435
  }
395
436
 
396
437
  return message;
@@ -463,7 +504,7 @@ export default class Validator {
463
504
  }
464
505
 
465
506
  for (const rule of rules) {
466
- if (this.#rules[attribute].hasOwnProperty(rule)) {
507
+ if (this.#rules[attribute].some((attributeRule) => attributeRule[0] === rule)) {
467
508
  return true;
468
509
  }
469
510
  }
@@ -24,6 +24,53 @@ describe('Validation', () => {
24
24
  });
25
25
  });
26
26
 
27
+ describe(`Invalid rule`, () => {
28
+ it(`Fails when the rule is invalid`, async () => {
29
+ const validator = new Validator({ field: 'abc' }, { field: 'foobar' });
30
+
31
+ try {
32
+ await validator.passes();
33
+ assert.fail('Invalid rule should throw an error');
34
+ } catch (error) {
35
+ assert.equal(error.message, 'Invalid validation rule: foobar');
36
+ }
37
+ });
38
+ });
39
+
40
+ describe(`Closure rule`, () => {
41
+ const rules = {
42
+ field: function (attribute, value) {
43
+ return /^[a-z]/i.test(value);
44
+ },
45
+ };
46
+
47
+ it(`Passes when the value starts with a letter`, async () => {
48
+ const validator = new Validator({ field: 'abc' }, rules);
49
+ assert(await validator.passes());
50
+ });
51
+
52
+ it(`Fails when the value does not start with a letter`, async () => {
53
+ const validator = new Validator({ field: 123 }, rules);
54
+ assert(await validator.fails());
55
+ });
56
+
57
+ it(`Passes when the error message is correct`, async () => {
58
+ const validator = new Validator(
59
+ { field: 123 },
60
+ {
61
+ field: function (attribute, value) {
62
+ return {
63
+ success: /^[a-z]/i.test(value),
64
+ message: 'The :attribute must start with a letter.',
65
+ };
66
+ },
67
+ },
68
+ );
69
+
70
+ assert.equal((await validator.validate()).first('field'), 'The field must start with a letter.');
71
+ });
72
+ });
73
+
27
74
  describe(`Rule 'accepted'`, () => {
28
75
  const rules = { field: 'accepted' };
29
76
 
@@ -79,6 +126,34 @@ describe('Validation', () => {
79
126
  const validator = new Validator({ field: true, other: 'bar' }, rules);
80
127
  assert(await validator.passes());
81
128
  });
129
+
130
+ const rules2 = { field: ['accepted_if:other1,foo', 'accepted_if:other2,bar'] };
131
+
132
+ it(`Passes when accepted if other fields' value are equal to provided values`, async () => {
133
+ const validator = new Validator({ field: true, other1: 'foo', other2: 'bar' }, rules2);
134
+ assert(await validator.passes());
135
+ });
136
+
137
+ it(`Fails when declined if other fields' value are equal to provided values`, async () => {
138
+ const validator = new Validator({ field: false, other1: 'foo', other2: 'bar' }, rules2);
139
+ assert(await validator.fails());
140
+ });
141
+
142
+ it(`Passes when accepted if any other fields' value is equal to provided value`, async () => {
143
+ const validator = new Validator({ field: true, other1: 'foo', other2: 'baz' }, rules2);
144
+ assert(await validator.passes());
145
+
146
+ validator.setData({ field: true, other1: 'baz', other2: 'bar' });
147
+ assert(await validator.passes());
148
+ });
149
+
150
+ it(`Fails when declined if any other fields' value is equal to provided value`, async () => {
151
+ const validator = new Validator({ field: false, other1: 'foo', other2: 'baz' }, rules2);
152
+ assert(await validator.fails());
153
+
154
+ validator.setData({ field: false, other1: 'baz', other2: 'bar' });
155
+ assert(await validator.fails());
156
+ });
82
157
  });
83
158
 
84
159
  describe(`Rule 'after'`, () => {
@@ -632,6 +707,34 @@ describe('Validation', () => {
632
707
  const validator = new Validator({ field: true, other: 'bar' }, rules);
633
708
  assert(await validator.passes());
634
709
  });
710
+
711
+ const rules2 = { field: ['declined_if:other1,foo', 'declined_if:other2,bar'] };
712
+
713
+ it(`Passes when declined if other fields' value are equal to provided values`, async () => {
714
+ const validator = new Validator({ field: false, other1: 'foo', other2: 'bar' }, rules2);
715
+ assert(await validator.passes());
716
+ });
717
+
718
+ it(`Fails when accepted if other fields' value are equal to provided values`, async () => {
719
+ const validator = new Validator({ field: true, other1: 'foo', other2: 'bar' }, rules2);
720
+ assert(await validator.fails());
721
+ });
722
+
723
+ it(`Passes when declined if any other fields' value is equal to provided value`, async () => {
724
+ const validator = new Validator({ field: false, other1: 'foo', other2: 'baz' }, rules2);
725
+ assert(await validator.passes());
726
+
727
+ validator.setData({ field: false, other1: 'baz', other2: 'bar' });
728
+ assert(await validator.passes());
729
+ });
730
+
731
+ it(`Fails when accepted if any other fields' value is equal to provided value`, async () => {
732
+ const validator = new Validator({ field: true, other1: 'foo', other2: 'baz' }, rules2);
733
+ assert(await validator.fails());
734
+
735
+ validator.setData({ field: true, other1: 'baz', other2: 'bar' });
736
+ assert(await validator.fails());
737
+ });
635
738
  });
636
739
 
637
740
  describe(`Rule 'different'`, () => {
@@ -1917,6 +2020,26 @@ describe('Validation', () => {
1917
2020
  const validator = new Validator({ field: '', other: 'bar' }, rules);
1918
2021
  assert(await validator.fails());
1919
2022
  });
2023
+
2024
+ const rules2 = { field: ['missing_if:other1,foo,bar', 'missing_if:other2,win,amp'] };
2025
+
2026
+ it(`Passes when the field is present and other fields' value are not equal to provided values`, async () => {
2027
+ const validator = new Validator({ field: '', other1: 'baz', other2: 'rar' }, rules2);
2028
+ assert(await validator.passes());
2029
+ });
2030
+
2031
+ it(`Fails when the field is present and other fields' value are equal to provided values`, async () => {
2032
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'win' }, rules2);
2033
+ assert(await validator.fails());
2034
+ });
2035
+
2036
+ it(`Fails when the field is present and any other fields' value is equal to provided value`, async () => {
2037
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'rar' }, rules2);
2038
+ assert(await validator.fails());
2039
+
2040
+ validator.setData({ field: '', other1: 'baz', other2: 'win' });
2041
+ assert(await validator.fails());
2042
+ });
1920
2043
  });
1921
2044
 
1922
2045
  describe(`Rule 'missing_unless'`, () => {
@@ -1941,6 +2064,26 @@ describe('Validation', () => {
1941
2064
  const validator = new Validator({ field: '', other: 'bob' }, rules);
1942
2065
  assert(await validator.fails());
1943
2066
  });
2067
+
2068
+ const rules2 = { field: ['missing_unless:other1,foo,bar', 'missing_unless:other2,win,amp'] };
2069
+
2070
+ it(`Passes when the field is present and other fields' value are equal to provided values`, async () => {
2071
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'win' }, rules2);
2072
+ assert(await validator.passes());
2073
+ });
2074
+
2075
+ it(`Fails when the field is present and other fields' value are not equal to provided values`, async () => {
2076
+ const validator = new Validator({ field: '', other1: 'baz', other2: 'rar' }, rules2);
2077
+ assert(await validator.fails());
2078
+ });
2079
+
2080
+ it(`Fails when the field is present and any other fields' value is not equal to provided value`, async () => {
2081
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'rar' }, rules2);
2082
+ assert(await validator.fails());
2083
+
2084
+ validator.setData({ field: '', other1: 'baz', other2: 'win' });
2085
+ assert(await validator.fails());
2086
+ });
1944
2087
  });
1945
2088
 
1946
2089
  describe(`Rule 'missing_with'`, () => {
@@ -2153,6 +2296,26 @@ describe('Validation', () => {
2153
2296
  const validator = new Validator({ field: 'abc', other: 'bar' }, rules);
2154
2297
  assert(await validator.fails());
2155
2298
  });
2299
+
2300
+ const rules2 = { field: ['prohibited_if:other1,foo,bar', 'prohibited_if:other2,win,amp'] };
2301
+
2302
+ it(`Passes when the field is filled and other fields' value are not equal to provided values`, async () => {
2303
+ const validator = new Validator({ field: 'abc', other1: 'baz', other2: 'rar' }, rules2);
2304
+ assert(await validator.passes());
2305
+ });
2306
+
2307
+ it(`Fails when the field is filled and other fields' value are equal to provided values`, async () => {
2308
+ const validator = new Validator({ field: 'abc', other1: 'foo', other2: 'win' }, rules2);
2309
+ assert(await validator.fails());
2310
+ });
2311
+
2312
+ it(`Fails when the field is filled and any other fields' value is equal to provided value`, async () => {
2313
+ const validator = new Validator({ field: 'abc', other1: 'foo', other2: 'rar' }, rules2);
2314
+ assert(await validator.fails());
2315
+
2316
+ validator.setData({ field: 'abc', other1: 'baz', other2: 'win' });
2317
+ assert(await validator.fails());
2318
+ });
2156
2319
  });
2157
2320
 
2158
2321
  describe(`Rule 'prohibited_unless'`, () => {
@@ -2177,6 +2340,26 @@ describe('Validation', () => {
2177
2340
  const validator = new Validator({ field: 'abc', other: 'bob' }, rules);
2178
2341
  assert(await validator.fails());
2179
2342
  });
2343
+
2344
+ const rules2 = { field: ['prohibited_unless:other1,foo,bar', 'prohibited_unless:other2,win,amp'] };
2345
+
2346
+ it(`Passes when the field is filled and other fields' value are equal to provided values`, async () => {
2347
+ const validator = new Validator({ field: 'abc', other1: 'foo', other2: 'win' }, rules2);
2348
+ assert(await validator.passes());
2349
+ });
2350
+
2351
+ it(`Fails when the field is filled and other fields' value are not equal to provided values`, async () => {
2352
+ const validator = new Validator({ field: 'abc', other1: 'baz', other2: 'rar' }, rules2);
2353
+ assert(await validator.fails());
2354
+ });
2355
+
2356
+ it(`Fails when the field is filled and any other fields' value is not equal to provided value`, async () => {
2357
+ const validator = new Validator({ field: 'abc', other1: 'foo', other2: 'rar' }, rules2);
2358
+ assert(await validator.fails());
2359
+
2360
+ validator.setData({ field: 'abc', other1: 'baz', other2: 'win' });
2361
+ assert(await validator.fails());
2362
+ });
2180
2363
  });
2181
2364
 
2182
2365
  describe(`Rule 'prohibits'`, () => {
@@ -2291,6 +2474,26 @@ describe('Validation', () => {
2291
2474
  const validator = new Validator({ field: '', other: 'bar' }, rules);
2292
2475
  assert(await validator.fails());
2293
2476
  });
2477
+
2478
+ const rules2 = { field: ['required_if:other1,foo,bar', 'required_if:other2,win,amp'] };
2479
+
2480
+ it(`Passes when the field is empty and other fields' value are not equal to provided values`, async () => {
2481
+ const validator = new Validator({ field: '', other1: 'baz', other2: 'rar' }, rules2);
2482
+ assert(await validator.passes());
2483
+ });
2484
+
2485
+ it(`Fails when the field is empty and other fields' value are equal to provided values`, async () => {
2486
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'win' }, rules2);
2487
+ assert(await validator.fails());
2488
+ });
2489
+
2490
+ it(`Fails when the field is empty and any other fields' value is equal to provided value`, async () => {
2491
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'rar' }, rules2);
2492
+ assert(await validator.fails());
2493
+
2494
+ validator.setData({ field: '', other1: 'baz', other2: 'win' });
2495
+ assert(await validator.fails());
2496
+ });
2294
2497
  });
2295
2498
 
2296
2499
  describe(`Rule 'required_if_accepted'`, () => {
@@ -2315,6 +2518,26 @@ describe('Validation', () => {
2315
2518
  const validator = new Validator({ field: '', foo: true }, rules);
2316
2519
  assert(await validator.fails());
2317
2520
  });
2521
+
2522
+ const rules2 = { field: ['required_if_accepted:other1', 'required_if_accepted:other2'] };
2523
+
2524
+ it(`Passes when the field is empty and other fields are declined`, async () => {
2525
+ const validator = new Validator({ field: '', other1: false, other2: false }, rules2);
2526
+ assert(await validator.passes());
2527
+ });
2528
+
2529
+ it(`Fails when the field is empty and all fields are accepted`, async () => {
2530
+ const validator = new Validator({ field: '', other1: true, other2: true }, rules2);
2531
+ assert(await validator.fails());
2532
+ });
2533
+
2534
+ it(`Fails when the field is empty and any field is accepted`, async () => {
2535
+ const validator = new Validator({ field: '', other1: true, other2: false }, rules2);
2536
+ assert(await validator.fails());
2537
+
2538
+ validator.setData({ field: '', other1: false, other2: true });
2539
+ assert(await validator.fails());
2540
+ });
2318
2541
  });
2319
2542
 
2320
2543
  describe(`Rule 'required_if_declined'`, () => {
@@ -2339,6 +2562,26 @@ describe('Validation', () => {
2339
2562
  const validator = new Validator({ field: '', foo: false }, rules);
2340
2563
  assert(await validator.fails());
2341
2564
  });
2565
+
2566
+ const rules2 = { field: ['required_if_declined:other1', 'required_if_declined:other2'] };
2567
+
2568
+ it(`Passes when the field is empty and other fields are accepted`, async () => {
2569
+ const validator = new Validator({ field: '', other1: true, other2: true }, rules2);
2570
+ assert(await validator.passes());
2571
+ });
2572
+
2573
+ it(`Fails when the field is empty and all fields are declined`, async () => {
2574
+ const validator = new Validator({ field: '', other1: false, other2: false }, rules2);
2575
+ assert(await validator.fails());
2576
+ });
2577
+
2578
+ it(`Fails when the field is empty and any field is declined`, async () => {
2579
+ const validator = new Validator({ field: '', other1: true, other2: false }, rules2);
2580
+ assert(await validator.fails());
2581
+
2582
+ validator.setData({ field: '', other1: false, other2: true });
2583
+ assert(await validator.fails());
2584
+ });
2342
2585
  });
2343
2586
 
2344
2587
  describe(`Rule 'required_unless'`, () => {
@@ -2363,6 +2606,26 @@ describe('Validation', () => {
2363
2606
  const validator = new Validator({ field: '', other: 'bob' }, rules);
2364
2607
  assert(await validator.fails());
2365
2608
  });
2609
+
2610
+ const rules2 = { field: ['required_unless:other1,foo,bar', 'required_unless:other2,win,amp'] };
2611
+
2612
+ it(`Passes when the field is empty and other fields' value are equal to provided values`, async () => {
2613
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'win' }, rules2);
2614
+ assert(await validator.passes());
2615
+ });
2616
+
2617
+ it(`Fails when the field is empty and other fields' value are not equal to provided values`, async () => {
2618
+ const validator = new Validator({ field: '', other1: 'baz', other2: 'rar' }, rules2);
2619
+ assert(await validator.fails());
2620
+ });
2621
+
2622
+ it(`Fails when the field is empty and any other fields' value is not equal to provided value`, async () => {
2623
+ const validator = new Validator({ field: '', other1: 'foo', other2: 'rar' }, rules2);
2624
+ assert(await validator.fails());
2625
+
2626
+ validator.setData({ field: '', other1: 'baz', other2: 'win' });
2627
+ assert(await validator.fails());
2628
+ });
2366
2629
  });
2367
2630
 
2368
2631
  describe(`Rule 'required_with'`, () => {