quival 0.3.4 → 0.4.1
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 +14 -1
- package/dist/locales/en.js +1 -1
- package/dist/locales/en.min.js +1 -1
- package/dist/locales/ms.js +1 -1
- package/dist/locales/ms.min.js +1 -1
- package/dist/quival.js +67 -25
- package/dist/quival.min.js +2 -2
- package/package.json +1 -1
- package/src/Validator.js +72 -25
- package/test/validation.js +263 -0
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.
|
|
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
|
],
|
package/dist/locales/en.js
CHANGED
package/dist/locales/en.min.js
CHANGED
package/dist/locales/ms.js
CHANGED
package/dist/locales/ms.min.js
CHANGED
package/dist/quival.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* quival v0.
|
|
2
|
+
* quival v0.4.1 (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
|
*/
|
|
@@ -1309,7 +1309,9 @@ var quival = (function (exports) {
|
|
|
1309
1309
|
this.#implicitAttributes = {};
|
|
1310
1310
|
this.#stopOnFirstFailure = false;
|
|
1311
1311
|
this.#alwaysBail = false;
|
|
1312
|
+
this.arrayRules = ['array', 'list'];
|
|
1312
1313
|
this.fileRules = ['file', 'image', 'mimetypes', 'mimes'];
|
|
1314
|
+
this.stringRules = ['string', 'alpha', 'alpha_dash', 'alpha_num', 'ascii', 'email'];
|
|
1313
1315
|
this.numericRules = ['decimal', 'numeric', 'integer'];
|
|
1314
1316
|
this.sizeRules = ['size', 'between', 'min', 'max', 'gt', 'lt', 'gte', 'lte'];
|
|
1315
1317
|
this.setProperties(data, rules, messages, attributes, values);
|
|
@@ -1368,10 +1370,9 @@ var quival = (function (exports) {
|
|
|
1368
1370
|
for (const [attribute, attributeRules] of Object.entries(rules)) {
|
|
1369
1371
|
const attributes = attribute.includes('*') ? this.parseWildcardAttribute(attribute) : [attribute];
|
|
1370
1372
|
for (const attribute of attributes) {
|
|
1371
|
-
const parsedAttributeRules =
|
|
1373
|
+
const parsedAttributeRules = [];
|
|
1372
1374
|
for (const attributeRule of this.parseAttributeRules(attributeRules)) {
|
|
1373
|
-
|
|
1374
|
-
parsedAttributeRules[rule] = parameters;
|
|
1375
|
+
parsedAttributeRules.push(this.parseAttributeRule(attributeRule));
|
|
1375
1376
|
}
|
|
1376
1377
|
parsedRules[attribute] = parsedAttributeRules;
|
|
1377
1378
|
}
|
|
@@ -1398,13 +1399,17 @@ var quival = (function (exports) {
|
|
|
1398
1399
|
parseAttributeRules(rules) {
|
|
1399
1400
|
if (Array.isArray(rules)) {
|
|
1400
1401
|
return rules;
|
|
1402
|
+
} else if (typeof rules === 'function') {
|
|
1403
|
+
return [rules];
|
|
1401
1404
|
} else {
|
|
1402
1405
|
return String(rules).split('|');
|
|
1403
1406
|
}
|
|
1404
1407
|
}
|
|
1405
1408
|
parseAttributeRule(rule) {
|
|
1406
1409
|
if (Array.isArray(rule)) {
|
|
1407
|
-
return [rule
|
|
1410
|
+
return [rule[0] ?? '', rule.slice(1)];
|
|
1411
|
+
} else if (typeof rule === 'function') {
|
|
1412
|
+
return [rule, []];
|
|
1408
1413
|
}
|
|
1409
1414
|
const index = rule.indexOf(':');
|
|
1410
1415
|
if (index === -1) {
|
|
@@ -1418,39 +1423,61 @@ var quival = (function (exports) {
|
|
|
1418
1423
|
this.#errors = new ErrorBag();
|
|
1419
1424
|
const tasks = [];
|
|
1420
1425
|
const skippedAttributes = [];
|
|
1426
|
+
for (const [attribute, rules] of Object.entries(this.#rules)) {
|
|
1427
|
+
for (const [rule] of rules) {
|
|
1428
|
+
if (
|
|
1429
|
+
rule === '' ||
|
|
1430
|
+
typeof rule === 'function' ||
|
|
1431
|
+
typeof this.#checkers[toCamelCase('check_' + rule)] === 'function' ||
|
|
1432
|
+
Validator.#dummyRules.includes(rule)
|
|
1433
|
+
)
|
|
1434
|
+
continue;
|
|
1435
|
+
throw new Error(`Invalid validation rule: ${rule}`);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1421
1438
|
for (const [attribute, rules] of Object.entries(this.#rules)) {
|
|
1422
1439
|
let value = this.getValue(attribute);
|
|
1423
|
-
|
|
1440
|
+
const hasRule = (ruleName) => rules.some((rule) => rule[0] === ruleName);
|
|
1441
|
+
if (hasRule('sometimes') && typeof value === 'undefined') {
|
|
1424
1442
|
skippedAttributes.push(attribute);
|
|
1425
1443
|
continue;
|
|
1426
1444
|
}
|
|
1427
1445
|
tasks.push(async () => {
|
|
1428
|
-
const doBail = this.#alwaysBail ||
|
|
1429
|
-
const isNullable =
|
|
1446
|
+
const doBail = this.#alwaysBail || hasRule('bail');
|
|
1447
|
+
const isNullable = hasRule('nullable');
|
|
1430
1448
|
let noError = true;
|
|
1431
|
-
for (const [rule, parameters] of
|
|
1449
|
+
for (const [rule, parameters] of rules) {
|
|
1432
1450
|
if (
|
|
1433
1451
|
rule === '' ||
|
|
1434
|
-
(
|
|
1452
|
+
(typeof rule !== 'function' &&
|
|
1453
|
+
!Validator.#implicitRules.includes(rule) &&
|
|
1435
1454
|
(typeof value === 'undefined' || (typeof value === 'string' && value.trim() === '') || (isNullable && value === null)))
|
|
1436
1455
|
) {
|
|
1437
1456
|
skippedAttributes.push(attribute);
|
|
1438
1457
|
continue;
|
|
1439
1458
|
}
|
|
1440
1459
|
let result, success, message;
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1460
|
+
const checker = (() => {
|
|
1461
|
+
if (typeof rule === 'function') {
|
|
1462
|
+
return rule;
|
|
1463
|
+
} else {
|
|
1464
|
+
const checker = this.#checkers[toCamelCase('check_' + rule)] ?? null;
|
|
1465
|
+
if (checker === null && Validator.#dummyRules.includes(rule)) {
|
|
1466
|
+
return () => true;
|
|
1467
|
+
}
|
|
1468
|
+
return checker;
|
|
1469
|
+
}
|
|
1470
|
+
})();
|
|
1471
|
+
if (checker === null) {
|
|
1447
1472
|
throw new Error(`Invalid validation rule: ${rule}`);
|
|
1448
1473
|
}
|
|
1474
|
+
result = await checker.call(this.#checkers, attribute, value, parameters);
|
|
1449
1475
|
if (typeof result === 'boolean') {
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1476
|
+
result = {
|
|
1477
|
+
success: result,
|
|
1478
|
+
};
|
|
1453
1479
|
}
|
|
1480
|
+
({ success, message = '' } = result);
|
|
1454
1481
|
if (!success) {
|
|
1455
1482
|
noError = false;
|
|
1456
1483
|
message = isEmpty(message) ? this.getMessage(attribute, rule) : message;
|
|
@@ -1469,7 +1496,13 @@ var quival = (function (exports) {
|
|
|
1469
1496
|
if (!(await task())) break;
|
|
1470
1497
|
}
|
|
1471
1498
|
} else {
|
|
1472
|
-
await Promise.allSettled(tasks.map((task) => task()))
|
|
1499
|
+
await Promise.allSettled(tasks.map((task) => task())).then((results) => {
|
|
1500
|
+
for (const result of results) {
|
|
1501
|
+
if (result.status === 'rejected') {
|
|
1502
|
+
throw result.reason;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
});
|
|
1473
1506
|
this.#errors.sortByKeys(Object.keys(this.#rules));
|
|
1474
1507
|
}
|
|
1475
1508
|
this.#skippedAttributes = skippedAttributes.filter((value, index, array) => array.indexOf(value) === index);
|
|
@@ -1486,6 +1519,9 @@ var quival = (function (exports) {
|
|
|
1486
1519
|
return !(await this.passes());
|
|
1487
1520
|
}
|
|
1488
1521
|
getMessage(attribute, rule) {
|
|
1522
|
+
if (typeof rule === 'function') {
|
|
1523
|
+
return '';
|
|
1524
|
+
}
|
|
1489
1525
|
const value = this.getValue(attribute);
|
|
1490
1526
|
attribute = this.getPrimaryAttribute(attribute);
|
|
1491
1527
|
let message;
|
|
@@ -1498,10 +1534,12 @@ var quival = (function (exports) {
|
|
|
1498
1534
|
if (!message) {
|
|
1499
1535
|
let key = rule;
|
|
1500
1536
|
if (this.sizeRules.includes(key)) {
|
|
1501
|
-
if (Array.isArray(value) || isPlainObject(value) || this.hasRule(attribute,
|
|
1537
|
+
if (Array.isArray(value) || isPlainObject(value) || this.hasRule(attribute, this.arrayRules)) {
|
|
1502
1538
|
key += '.array';
|
|
1503
1539
|
} else if (value instanceof File || this.hasRule(attribute, this.fileRules)) {
|
|
1504
1540
|
key += '.file';
|
|
1541
|
+
} else if (this.hasRule(attribute, this.stringRules)) {
|
|
1542
|
+
key += '.string';
|
|
1505
1543
|
} else if (isNumeric(value) || this.hasRule(attribute, this.numericRules)) {
|
|
1506
1544
|
key += '.numeric';
|
|
1507
1545
|
} else {
|
|
@@ -1529,9 +1567,11 @@ var quival = (function (exports) {
|
|
|
1529
1567
|
if (index !== -1) {
|
|
1530
1568
|
message = message.replaceAll(':index', index).replaceAll(':position', index + 1);
|
|
1531
1569
|
}
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1570
|
+
if (typeof rule === 'string') {
|
|
1571
|
+
const replacer = this.#replacers[toCamelCase('replace_' + rule)] ?? null;
|
|
1572
|
+
if (replacer) {
|
|
1573
|
+
message = replacer.call(this.#replacers, message, attribute, rule, parameters);
|
|
1574
|
+
}
|
|
1535
1575
|
}
|
|
1536
1576
|
return message;
|
|
1537
1577
|
}
|
|
@@ -1566,6 +1606,8 @@ var quival = (function (exports) {
|
|
|
1566
1606
|
getSize(attribute, value) {
|
|
1567
1607
|
if (isEmpty(value)) {
|
|
1568
1608
|
return 0;
|
|
1609
|
+
} else if (this.hasRule(attribute, this.stringRules)) {
|
|
1610
|
+
return String(value).length;
|
|
1569
1611
|
} else if (isNumeric(value) && this.hasRule(attribute, this.numericRules)) {
|
|
1570
1612
|
return parseFloat(typeof value === 'string' ? value.trim() : value, 10);
|
|
1571
1613
|
} else if (value instanceof File) {
|
|
@@ -1588,7 +1630,7 @@ var quival = (function (exports) {
|
|
|
1588
1630
|
return false;
|
|
1589
1631
|
}
|
|
1590
1632
|
for (const rule of rules) {
|
|
1591
|
-
if (this.#rules[attribute].
|
|
1633
|
+
if (this.#rules[attribute].some((attributeRule) => attributeRule[0] === rule)) {
|
|
1592
1634
|
return true;
|
|
1593
1635
|
}
|
|
1594
1636
|
}
|
package/dist/quival.min.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* quival v0.
|
|
2
|
+
* quival v0.4.1 (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],p=a[i.hours]??0,d=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()&&p<12&&(p+=12),new Date(`${l}-${h}-${o} ${p}:${d}:${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 p=`"${r(c.substring(a)).replaceAll("\\*",'[^."]+')}":`,d=0;return p+=h?"string"==typeof t?`"${o}"`:`${o}`:`(${o}|"${o}")`,p+="[,}]+",d+=u.match(new RegExp(p,"g"+(l?"i":"")))?.length??0,1===d}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 p{#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 d{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;#p;#d;#f;#g;#m;#k;#b;#y;static setLocale(e){d.locale(e)}static setMessages(e,t){d.setMessages(e,t)}static addChecker(e,t,r){g.#c[e]=t,r&&d.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.#y=!1,this.arrayRules=["array","list"],this.fileRules=["file","image","mimetypes","mimes"],this.stringRules=["string","alpha","alpha_dash","alpha_num","ascii","email"],this.numericRules=["decimal","numeric","integer"],this.sizeRules=["size","between","min","max","gt","lt","gte","lte"],this.setProperties(e,r,s,i,c),this.#d=new o(this),this.#f=new f(this);for(const[e,r]of Object.entries(g.#c))this.#d[t("check_"+e)]=r;for(const[e,r]of Object.entries(g.#a))this.#f[t("replace_"+e)]=r;this.#g=new p}setProperties(e={},t={},r={},i={},c={}){return this.#r=e,this.#l=this.parseRules(t),this.#h=r,this.#o=i,this.#p=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.#p=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.#y=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.#d.clearCaches(),this.#g=new p;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.#d[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.#y||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,p;const d=(()=>{if("function"==typeof a)return a;{const e=this.#d[t("check_"+a)]??null;return null===e&&g.#n.includes(a)?()=>!0:e}})();if(null===d)throw new Error(`Invalid validation rule: ${a}`);if(i=await d.call(this.#d,s,c,h),"boolean"==typeof i&&(i={success:i}),({success:o,message:p=""}=i),!o&&(l=!1,p=n(p)?this.getMessage(s,a):p,p=this.makeReplacements(p,s,a,h),this.#g.add(s,p),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,this.arrayRules)?i+=".array":r instanceof File||this.hasRule(e,this.fileRules)?i+=".file":this.hasRule(e,this.stringRules)?i+=".string":u(r)||this.hasRule(e,this.numericRules)?i+=".numeric":i+=".string"),s=d.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(d.has(`attributes.${r}`))return d.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.#p,r)?this.#p[r]:d.has(`values.${r}`)?d.get(`values.${r}`):t}getSize(e,t){return n(t)?0:this.hasRule(e,this.stringRules)?String(t).length: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=p,e.Lang=d,e.Replacers=f,e.Validator=g,e}({});
|
package/package.json
CHANGED
package/src/Validator.js
CHANGED
|
@@ -63,7 +63,9 @@ export default class Validator {
|
|
|
63
63
|
#stopOnFirstFailure = false;
|
|
64
64
|
#alwaysBail = false;
|
|
65
65
|
|
|
66
|
+
arrayRules = ['array', 'list'];
|
|
66
67
|
fileRules = ['file', 'image', 'mimetypes', 'mimes'];
|
|
68
|
+
stringRules = ['string', 'alpha', 'alpha_dash', 'alpha_num', 'ascii', 'email'];
|
|
67
69
|
numericRules = ['decimal', 'numeric', 'integer'];
|
|
68
70
|
sizeRules = ['size', 'between', 'min', 'max', 'gt', 'lt', 'gte', 'lte'];
|
|
69
71
|
|
|
@@ -178,12 +180,10 @@ export default class Validator {
|
|
|
178
180
|
const attributes = attribute.includes('*') ? this.parseWildcardAttribute(attribute) : [attribute];
|
|
179
181
|
|
|
180
182
|
for (const attribute of attributes) {
|
|
181
|
-
const parsedAttributeRules =
|
|
183
|
+
const parsedAttributeRules = [];
|
|
182
184
|
|
|
183
185
|
for (const attributeRule of this.parseAttributeRules(attributeRules)) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
parsedAttributeRules[rule] = parameters;
|
|
186
|
+
parsedAttributeRules.push(this.parseAttributeRule(attributeRule));
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
parsedRules[attribute] = parsedAttributeRules;
|
|
@@ -218,6 +218,8 @@ export default class Validator {
|
|
|
218
218
|
parseAttributeRules(rules) {
|
|
219
219
|
if (Array.isArray(rules)) {
|
|
220
220
|
return rules;
|
|
221
|
+
} else if (typeof rules === 'function') {
|
|
222
|
+
return [rules];
|
|
221
223
|
} else {
|
|
222
224
|
return String(rules).split('|');
|
|
223
225
|
}
|
|
@@ -225,7 +227,9 @@ export default class Validator {
|
|
|
225
227
|
|
|
226
228
|
parseAttributeRule(rule) {
|
|
227
229
|
if (Array.isArray(rule)) {
|
|
228
|
-
return [rule
|
|
230
|
+
return [rule[0] ?? '', rule.slice(1)];
|
|
231
|
+
} else if (typeof rule === 'function') {
|
|
232
|
+
return [rule, []];
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
const index = rule.indexOf(':');
|
|
@@ -244,23 +248,39 @@ export default class Validator {
|
|
|
244
248
|
const tasks = [];
|
|
245
249
|
const skippedAttributes = [];
|
|
246
250
|
|
|
251
|
+
for (const [attribute, rules] of Object.entries(this.#rules)) {
|
|
252
|
+
for (const [rule] of rules) {
|
|
253
|
+
if (
|
|
254
|
+
rule === '' ||
|
|
255
|
+
typeof rule === 'function' ||
|
|
256
|
+
typeof this.#checkers[toCamelCase('check_' + rule)] === 'function' ||
|
|
257
|
+
Validator.#dummyRules.includes(rule)
|
|
258
|
+
)
|
|
259
|
+
continue;
|
|
260
|
+
|
|
261
|
+
throw new Error(`Invalid validation rule: ${rule}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
247
265
|
for (const [attribute, rules] of Object.entries(this.#rules)) {
|
|
248
266
|
let value = this.getValue(attribute);
|
|
267
|
+
const hasRule = (ruleName) => rules.some((rule) => rule[0] === ruleName);
|
|
249
268
|
|
|
250
|
-
if (
|
|
269
|
+
if (hasRule('sometimes') && typeof value === 'undefined') {
|
|
251
270
|
skippedAttributes.push(attribute);
|
|
252
271
|
continue;
|
|
253
272
|
}
|
|
254
273
|
|
|
255
274
|
tasks.push(async () => {
|
|
256
|
-
const doBail = this.#alwaysBail ||
|
|
257
|
-
const isNullable =
|
|
275
|
+
const doBail = this.#alwaysBail || hasRule('bail');
|
|
276
|
+
const isNullable = hasRule('nullable');
|
|
258
277
|
let noError = true;
|
|
259
278
|
|
|
260
|
-
for (const [rule, parameters] of
|
|
279
|
+
for (const [rule, parameters] of rules) {
|
|
261
280
|
if (
|
|
262
281
|
rule === '' ||
|
|
263
|
-
(
|
|
282
|
+
(typeof rule !== 'function' &&
|
|
283
|
+
!Validator.#implicitRules.includes(rule) &&
|
|
264
284
|
(typeof value === 'undefined' || (typeof value === 'string' && value.trim() === '') || (isNullable && value === null)))
|
|
265
285
|
) {
|
|
266
286
|
skippedAttributes.push(attribute);
|
|
@@ -268,22 +288,33 @@ export default class Validator {
|
|
|
268
288
|
}
|
|
269
289
|
|
|
270
290
|
let result, success, message;
|
|
271
|
-
const camelRule = toCamelCase('check_' + rule);
|
|
272
291
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
292
|
+
const checker = (() => {
|
|
293
|
+
if (typeof rule === 'function') {
|
|
294
|
+
return rule;
|
|
295
|
+
} else {
|
|
296
|
+
const checker = this.#checkers[toCamelCase('check_' + rule)] ?? null;
|
|
297
|
+
|
|
298
|
+
if (checker === null && Validator.#dummyRules.includes(rule)) {
|
|
299
|
+
return () => true;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return checker;
|
|
303
|
+
}
|
|
304
|
+
})();
|
|
305
|
+
|
|
306
|
+
if (checker === null) {
|
|
278
307
|
throw new Error(`Invalid validation rule: ${rule}`);
|
|
279
308
|
}
|
|
280
309
|
|
|
310
|
+
result = await checker.call(this.#checkers, attribute, value, parameters);
|
|
311
|
+
|
|
281
312
|
if (typeof result === 'boolean') {
|
|
282
|
-
|
|
283
|
-
} else {
|
|
284
|
-
({ success, message } = result);
|
|
313
|
+
result = { success: result };
|
|
285
314
|
}
|
|
286
315
|
|
|
316
|
+
({ success, message = '' } = result);
|
|
317
|
+
|
|
287
318
|
if (!success) {
|
|
288
319
|
noError = false;
|
|
289
320
|
message = isEmpty(message) ? this.getMessage(attribute, rule) : message;
|
|
@@ -306,7 +337,13 @@ export default class Validator {
|
|
|
306
337
|
if (!(await task())) break;
|
|
307
338
|
}
|
|
308
339
|
} else {
|
|
309
|
-
await Promise.allSettled(tasks.map((task) => task()))
|
|
340
|
+
await Promise.allSettled(tasks.map((task) => task())).then((results) => {
|
|
341
|
+
for (const result of results) {
|
|
342
|
+
if (result.status === 'rejected') {
|
|
343
|
+
throw result.reason;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
310
347
|
|
|
311
348
|
this.#errors.sortByKeys(Object.keys(this.#rules));
|
|
312
349
|
}
|
|
@@ -331,6 +368,10 @@ export default class Validator {
|
|
|
331
368
|
}
|
|
332
369
|
|
|
333
370
|
getMessage(attribute, rule) {
|
|
371
|
+
if (typeof rule === 'function') {
|
|
372
|
+
return '';
|
|
373
|
+
}
|
|
374
|
+
|
|
334
375
|
const value = this.getValue(attribute);
|
|
335
376
|
attribute = this.getPrimaryAttribute(attribute);
|
|
336
377
|
|
|
@@ -348,10 +389,12 @@ export default class Validator {
|
|
|
348
389
|
let key = rule;
|
|
349
390
|
|
|
350
391
|
if (this.sizeRules.includes(key)) {
|
|
351
|
-
if (Array.isArray(value) || isPlainObject(value) || this.hasRule(attribute,
|
|
392
|
+
if (Array.isArray(value) || isPlainObject(value) || this.hasRule(attribute, this.arrayRules)) {
|
|
352
393
|
key += '.array';
|
|
353
394
|
} else if (value instanceof File || this.hasRule(attribute, this.fileRules)) {
|
|
354
395
|
key += '.file';
|
|
396
|
+
} else if (this.hasRule(attribute, this.stringRules)) {
|
|
397
|
+
key += '.string';
|
|
355
398
|
} else if (isNumeric(value) || this.hasRule(attribute, this.numericRules)) {
|
|
356
399
|
key += '.numeric';
|
|
357
400
|
} else {
|
|
@@ -387,10 +430,12 @@ export default class Validator {
|
|
|
387
430
|
message = message.replaceAll(':index', index).replaceAll(':position', index + 1);
|
|
388
431
|
}
|
|
389
432
|
|
|
390
|
-
|
|
433
|
+
if (typeof rule === 'string') {
|
|
434
|
+
const replacer = this.#replacers[toCamelCase('replace_' + rule)] ?? null;
|
|
391
435
|
|
|
392
|
-
|
|
393
|
-
|
|
436
|
+
if (replacer) {
|
|
437
|
+
message = replacer.call(this.#replacers, message, attribute, rule, parameters);
|
|
438
|
+
}
|
|
394
439
|
}
|
|
395
440
|
|
|
396
441
|
return message;
|
|
@@ -435,6 +480,8 @@ export default class Validator {
|
|
|
435
480
|
getSize(attribute, value) {
|
|
436
481
|
if (isEmpty(value)) {
|
|
437
482
|
return 0;
|
|
483
|
+
} else if (this.hasRule(attribute, this.stringRules)) {
|
|
484
|
+
return String(value).length;
|
|
438
485
|
} else if (isNumeric(value) && this.hasRule(attribute, this.numericRules)) {
|
|
439
486
|
return parseFloat(typeof value === 'string' ? value.trim() : value, 10);
|
|
440
487
|
} else if (value instanceof File) {
|
|
@@ -463,7 +510,7 @@ export default class Validator {
|
|
|
463
510
|
}
|
|
464
511
|
|
|
465
512
|
for (const rule of rules) {
|
|
466
|
-
if (this.#rules[attribute].
|
|
513
|
+
if (this.#rules[attribute].some((attributeRule) => attributeRule[0] === rule)) {
|
|
467
514
|
return true;
|
|
468
515
|
}
|
|
469
516
|
}
|
package/test/validation.js
CHANGED
|
@@ -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'`, () => {
|