quival 0.5.4 → 0.5.6

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * quival v0.5.4 (git+https://github.com/apih/quival.git)
2
+ * quival v0.5.6 (git+https://github.com/apih/quival.git)
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.5.4 (git+https://github.com/apih/quival.git)
2
+ * quival v0.5.6 (git+https://github.com/apih/quival.git)
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.5.4 (git+https://github.com/apih/quival.git)
2
+ * quival v0.5.6 (git+https://github.com/apih/quival.git)
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.5.4 (git+https://github.com/apih/quival.git)
2
+ * quival v0.5.6 (git+https://github.com/apih/quival.git)
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,11 +1,26 @@
1
1
  /*!
2
- * quival v0.5.4 (git+https://github.com/apih/quival.git)
2
+ * quival v0.5.6 (git+https://github.com/apih/quival.git)
3
3
  * (c) 2023 Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>
4
4
  * Released under the MIT License.
5
5
  */
6
6
  var quival = (function (exports) {
7
7
  'use strict';
8
8
 
9
+ const castToIntegers = (value) => (value && /^\d*$/.test(value) ? parseInt(value) : value);
10
+ const buildDate = (years, months, days, hours, minutes, seconds, meridiem) => {
11
+ if (years >= 10 && years < 100) {
12
+ years += 2000;
13
+ }
14
+ if (meridiem !== null) {
15
+ meridiem = meridiem.toLowerCase();
16
+ if (meridiem === 'pm' && hours < 12) {
17
+ hours += 12;
18
+ } else if (meridiem === 'am' && hours === 12) {
19
+ hours = 0;
20
+ }
21
+ }
22
+ return new Date(`${years}-${months}-${days} ${hours}:${minutes}:${seconds}`);
23
+ };
9
24
  function toCamelCase(string) {
10
25
  return string
11
26
  .replace(/[-_]/g, ' ')
@@ -74,59 +89,49 @@ var quival = (function (exports) {
74
89
  return new Date('');
75
90
  }
76
91
  let match, years, months, days, hours, minutes, seconds, meridiem;
77
- const castToIntegers = (value) => (value && /^\d*$/.test(value) ? parseInt(value) : value);
78
92
  if ((match = value.match(/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{2,4})\s?((\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?)?/i)) !== null) {
79
- [, days, months, years, , hours = 0, minutes = 0, , seconds = 0, meridiem = 'am'] = match.map(castToIntegers);
93
+ [, days, months, years, , hours = 0, minutes = 0, , seconds = 0, meridiem = null] = match.map(castToIntegers);
80
94
  } else if (
81
95
  (match = value.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 ||
82
96
  (match = value.match(/^(\d{4})(\d{2})(\d{2})\s?((\d{2})(\d{2})((\d{2}))?\s?(am|pm)?)?/i)) !== null
83
97
  ) {
84
- [, years, months, days, , hours = 0, minutes = 0, , seconds = 0, meridiem = 'am'] = match.map(castToIntegers);
98
+ [, years, months, days, , hours = 0, minutes = 0, , seconds = 0, meridiem = null] = match.map(castToIntegers);
85
99
  } else if ((match = value.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{4})[.\/-](\d{2})[.\/-](\d{2})/i))) {
86
- [, hours, minutes, , seconds, meridiem = 'am', years, months, days] = match.map(castToIntegers);
100
+ [, hours, minutes, , seconds, meridiem = null, years, months, days] = match.map(castToIntegers);
87
101
  } else if ((match = value.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{2})[.\/-](\d{2})[.\/-](\d{4})/i))) {
88
- [, hours, minutes, , seconds, meridiem = 'am', days, months, years] = match.map(castToIntegers);
102
+ [, hours, minutes, , seconds, meridiem = null, days, months, years] = match.map(castToIntegers);
89
103
  } else if ((match = value.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?/i))) {
90
104
  const current = new Date();
91
105
  years = current.getFullYear();
92
106
  months = current.getMonth() + 1;
93
107
  days = current.getDate();
94
- [, hours = 0, minutes = 0, , seconds = 0, meridiem = 'am'] = match.map(castToIntegers);
108
+ [, hours = 0, minutes = 0, , seconds = 0, meridiem = null] = match.map(castToIntegers);
95
109
  } else {
96
110
  return new Date(value);
97
111
  }
98
- if (years >= 10 && years < 100) {
99
- years += 2000;
100
- }
101
- meridiem = meridiem.toLowerCase();
102
- if (meridiem === 'pm' && hours < 12) {
103
- hours += 12;
104
- } else if (meridiem === 'am' && hours === 12) {
105
- hours = 0;
106
- }
107
- return new Date(`${years}-${months}-${days} ${hours}:${minutes}:${seconds}`);
112
+ return buildDate(years, months, days, hours, minutes, seconds, meridiem);
108
113
  }
114
+ const DATE_FORMAT_PATTERNS = {
115
+ Y: '(\\d{4})',
116
+ y: '(\\d{2})',
117
+ m: '(\\d{2})',
118
+ n: '([1-9]\\d?)',
119
+ d: '(\\d{2})',
120
+ j: '([1-9]\\d?)',
121
+ G: '([1-9]\\d?)',
122
+ g: '([1-9]\\d?)',
123
+ H: '(\\d{2})',
124
+ h: '(\\d{2})',
125
+ i: '(\\d{2})',
126
+ s: '(\\d{2})',
127
+ A: '(AM|PM)',
128
+ a: '(am|pm)',
129
+ };
109
130
  function parseDateByFormat(value, format) {
110
131
  if (isEmpty(value)) {
111
132
  return new Date('');
112
133
  }
113
134
  format = format.split('');
114
- const formats = {
115
- Y: '(\\d{4})',
116
- y: '(\\d{2})',
117
- m: '(\\d{2})',
118
- n: '([1-9]\\d?)',
119
- d: '(\\d{2})',
120
- j: '([1-9]\\d?)',
121
- G: '([1-9]\\d?)',
122
- g: '([1-9]\\d?)',
123
- H: '(\\d{2})',
124
- h: '(\\d{2})',
125
- i: '(\\d{2})',
126
- s: '(\\d{2})',
127
- A: '(AM|PM)',
128
- a: '(am|pm)',
129
- };
130
135
  let pattern = '^';
131
136
  let indices = {
132
137
  years: -1,
@@ -139,8 +144,8 @@ var quival = (function (exports) {
139
144
  };
140
145
  let index = 1;
141
146
  for (const char of format) {
142
- if (Object.hasOwn(formats, char)) {
143
- pattern += formats[char];
147
+ if (Object.hasOwn(DATE_FORMAT_PATTERNS, char)) {
148
+ pattern += DATE_FORMAT_PATTERNS[char];
144
149
  if (['Y', 'y'].indexOf(char) !== -1) {
145
150
  indices.years = index++;
146
151
  } else if (['m', 'n'].indexOf(char) !== -1) {
@@ -165,7 +170,7 @@ var quival = (function (exports) {
165
170
  if (match === null) {
166
171
  return new Date('');
167
172
  }
168
- match = match.map((value) => (value && /^\d*$/.test(value) ? parseInt(value) : value));
173
+ match = match.map(castToIntegers);
169
174
  const current = new Date();
170
175
  let years = match[indices.years];
171
176
  let months = match[indices.months];
@@ -173,7 +178,7 @@ var quival = (function (exports) {
173
178
  let hours = match[indices.hours] ?? 0;
174
179
  let minutes = match[indices.minutes] ?? 0;
175
180
  let seconds = match[indices.seconds] ?? 0;
176
- let meridiem = match[indices.meridiem] ?? 'am';
181
+ let meridiem = match[indices.meridiem] ?? null;
177
182
  if (!years && !months && !days) {
178
183
  years = current.getFullYear();
179
184
  months = current.getMonth() + 1;
@@ -188,16 +193,10 @@ var quival = (function (exports) {
188
193
  years = current.getFullYear();
189
194
  months = current.getMonth() + 1;
190
195
  }
191
- if (years >= 10 && years < 100) {
192
- years = years + 2000;
193
- }
194
- meridiem = meridiem.toLowerCase();
195
- if (meridiem === 'pm' && hours < 12) {
196
- hours += 12;
197
- } else if (meridiem === 'am' && hours === 12) {
198
- hours = 0;
199
- }
200
- return new Date(`${years}-${months}-${days} ${hours}:${minutes}:${seconds}`);
196
+ return buildDate(years, months, days, hours, minutes, seconds, meridiem);
197
+ }
198
+ function getDecimalPlaces(value) {
199
+ return (String(value).split('.')[1] ?? '').length;
201
200
  }
202
201
  function isDigits(value) {
203
202
  return String(value).search(/[^0-9]/) === -1;
@@ -233,35 +232,18 @@ var quival = (function (exports) {
233
232
  const other = this.validator.getValue(parameters[0]);
234
233
  return parameters.slice(1).some((value) => value == other);
235
234
  }
235
+ collectAndTest(checker, attribute, value, parameters, callback) {
236
+ const result = parameters.map((other) => checker(other, this.validator.getValue(other)));
237
+ return callback(result) ? checker(attribute, value) : true;
238
+ }
236
239
  collectRequiredsThenTest(attribute, value, parameters, callback) {
237
- let result = [];
238
- for (const other of parameters) {
239
- result.push(this.checkRequired(other, this.validator.getValue(other)));
240
- }
241
- if (callback(result)) {
242
- return this.checkRequired(attribute, value);
243
- }
244
- return true;
240
+ return this.collectAndTest(this.checkRequired, attribute, value, parameters, callback);
245
241
  }
246
242
  collectPresentsThenTest(attribute, value, parameters, callback) {
247
- let result = [];
248
- for (const other of parameters) {
249
- result.push(this.checkPresent(other, this.validator.getValue(other)));
250
- }
251
- if (callback(result)) {
252
- return this.checkPresent(attribute, value);
253
- }
254
- return true;
243
+ return this.collectAndTest(this.checkPresent, attribute, value, parameters, callback);
255
244
  }
256
245
  collectMissingsThenTest(attribute, value, parameters, callback) {
257
- let result = [];
258
- for (const other of parameters) {
259
- result.push(this.checkMissing(other, this.validator.getValue(other)));
260
- }
261
- if (callback(result)) {
262
- return this.checkMissing(attribute, value);
263
- }
264
- return true;
246
+ return this.collectAndTest(this.checkMissing, attribute, value, parameters, callback);
265
247
  }
266
248
  testStringUsingRegex(attribute, value, asciiRegex, unicodeRegex, isAscii = false) {
267
249
  if (typeof value !== 'string' && typeof value !== 'number') {
@@ -347,7 +329,7 @@ var quival = (function (exports) {
347
329
  }
348
330
  checkInteger(attribute, value, parameters = []) {
349
331
  if (!parameters.includes('strict') && typeof value === 'string') {
350
- value = parseFloat(value);
332
+ value = Number(value);
351
333
  }
352
334
  return Number.isInteger(value);
353
335
  }
@@ -375,8 +357,8 @@ var quival = (function (exports) {
375
357
  if (!isNumeric(value) || !isNumeric(parameters[0])) {
376
358
  return false;
377
359
  }
378
- const numerator = parseInt(value, 10);
379
- const denominator = parseInt(parameters[0], 10);
360
+ const numerator = Number(value);
361
+ const denominator = Number(parameters[0]);
380
362
  if (numerator === 0 && denominator === 0) {
381
363
  return false;
382
364
  } else if (numerator === 0) {
@@ -384,7 +366,9 @@ var quival = (function (exports) {
384
366
  } else if (denominator === 0) {
385
367
  return false;
386
368
  }
387
- return numerator % denominator === 0;
369
+ const decimalPlaces = Math.max(getDecimalPlaces(numerator), getDecimalPlaces(denominator));
370
+ const factor = 10 ** decimalPlaces;
371
+ return Math.round(numerator * factor) % Math.round(denominator * factor) === 0;
388
372
  }
389
373
  // Agreement
390
374
  checkAccepted(attribute, value, parameters) {
@@ -682,26 +666,10 @@ var quival = (function (exports) {
682
666
  }
683
667
  checkDateFormat(attribute, value, parameters) {
684
668
  const format = parameters[0].split('');
685
- const formats = {
686
- Y: '(\\d{4})',
687
- y: '(\\d{2})',
688
- m: '(\\d{2})',
689
- n: '([1-9]\\d?)',
690
- d: '(\\d{2})',
691
- j: '([1-9]\\d?)',
692
- G: '([1-9]\\d?)',
693
- g: '([1-9]\\d?)',
694
- H: '(\\d{2})',
695
- h: '(\\d{2})',
696
- i: '(\\d{2})',
697
- s: '(\\d{2})',
698
- A: '(AM|PM)',
699
- a: '(am|pm)',
700
- };
701
669
  let pattern = '^';
702
670
  for (const char of format) {
703
- if (Object.hasOwn(formats, char)) {
704
- pattern += formats[char];
671
+ if (Object.hasOwn(DATE_FORMAT_PATTERNS, char)) {
672
+ pattern += DATE_FORMAT_PATTERNS[char];
705
673
  } else {
706
674
  pattern += '\\' + char;
707
675
  }
@@ -714,8 +682,9 @@ var quival = (function (exports) {
714
682
  if (!this.checkArray(attribute, value)) {
715
683
  return false;
716
684
  }
685
+ const values = Array.isArray(value) ? value : Object.values(value);
717
686
  for (const parameter of parameters) {
718
- if (!value.includes(parameter)) {
687
+ if (!values.some((item) => item == parameter)) {
719
688
  return false;
720
689
  }
721
690
  }
@@ -725,8 +694,9 @@ var quival = (function (exports) {
725
694
  if (!this.checkArray(attribute, value)) {
726
695
  return false;
727
696
  }
697
+ const values = Array.isArray(value) ? value : Object.values(value);
728
698
  for (const parameter of parameters) {
729
- if (value.includes(parameter)) {
699
+ if (values.some((item) => item == parameter)) {
730
700
  return false;
731
701
  }
732
702
  }
@@ -842,10 +812,10 @@ var quival = (function (exports) {
842
812
  for (const parameter of parameters) {
843
813
  const [key, value] = parameter.split('=', 2);
844
814
  if (key === 'ratio' && value.includes('/')) {
845
- const [numerator, denominator] = value.split('/', 2).map((part) => parseFloat(part, 10));
815
+ const [numerator, denominator] = value.split('/', 2).map((part) => parseFloat(part));
846
816
  constraints[key] = numerator / denominator;
847
817
  } else {
848
- constraints[key] = parseFloat(value, 10);
818
+ constraints[key] = parseFloat(value);
849
819
  }
850
820
  }
851
821
  const image = this.#imageCache[attribute];
@@ -969,7 +939,7 @@ var quival = (function (exports) {
969
939
  return true;
970
940
  }
971
941
  checkUlid(attribute, value, parameters) {
972
- return /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/.test(value);
942
+ return /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i.test(value);
973
943
  }
974
944
  checkUuid(attribute, value, parameters) {
975
945
  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(value);
@@ -1089,11 +1059,14 @@ var quival = (function (exports) {
1089
1059
  }
1090
1060
  replaceCaseVariants(message, data) {
1091
1061
  Object.entries(data)
1092
- .flatMap(([key, value]) => [
1093
- [key, value],
1094
- [key.toLocaleUpperCase(), value.toLocaleUpperCase()],
1095
- [key.charAt(0).toLocaleUpperCase() + key.substring(1), value.charAt(0).toLocaleUpperCase() + value.substring(1)],
1096
- ])
1062
+ .flatMap(([key, value]) => {
1063
+ value = String(value);
1064
+ return [
1065
+ [key, value],
1066
+ [key.toLocaleUpperCase(), value.toLocaleUpperCase()],
1067
+ [key.charAt(0).toLocaleUpperCase() + key.substring(1), value.charAt(0).toLocaleUpperCase() + value.substring(1)],
1068
+ ];
1069
+ })
1097
1070
  .forEach(([key, value]) => (message = message.replaceAll(':' + key, value)));
1098
1071
  return message;
1099
1072
  }
@@ -1256,7 +1229,7 @@ var quival = (function (exports) {
1256
1229
  replaceGt(message, attribute, rule, parameters) {
1257
1230
  const value = this.validator.getValue(parameters[0]);
1258
1231
  return this.replace(message, {
1259
- value: value ? this.validator.getSize(parameters[0], value) : this.validator.getDisplayableAttribute(parameters[0]),
1232
+ value: typeof value === 'undefined' ? this.validator.getDisplayableAttribute(parameters[0]) : this.validator.getSize(parameters[0], value),
1260
1233
  });
1261
1234
  }
1262
1235
  replaceGte(message, attribute, rule, parameters) {
@@ -1722,7 +1695,7 @@ var quival = (function (exports) {
1722
1695
  } else if (this.hasRule(attribute, this.stringRules)) {
1723
1696
  return String(value).length;
1724
1697
  } else if (isNumeric(value) && this.hasRule(attribute, this.numericRules)) {
1725
- return parseFloat(typeof value === 'string' ? value.trim() : value, 10);
1698
+ return parseFloat(typeof value === 'string' ? value.trim() : value);
1726
1699
  } else if (value instanceof File) {
1727
1700
  return value.size / 1024;
1728
1701
  } else if (isPlainObject(value)) {
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * quival v0.5.4 (git+https://github.com/apih/quival.git)
2
+ * quival v0.5.6 (git+https://github.com/apih/quival.git)
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+/g," ").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){if(e instanceof Date)return e;if(a(e)||"string"!=typeof e)return new Date("");let t,r,s,i,c,n,l,u;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,n=0,,l=0,u="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,n=0,,l=0,u="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,n,,l,u="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,n,,l,u="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,n=0,,l=0,u="am"]=t.map(h)}}return r>=10&&r<100&&(r+=2e3),u=u.toLowerCase(),"pm"===u&&c<12?c+=12:"am"===u&&12===c&&(c=0),new Date(`${r}-${s}-${i} ${c}:${n}:${l}`)}function c(e,t){if(a(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 n=e.match(new RegExp(s));if(null===n)return new Date("");n=n.map(e=>e&&/^\d*$/.test(e)?parseInt(e):e);const l=new Date;let u=n[i.years],h=n[i.months],o=n[i.days],p=n[i.hours]??0,d=n[i.minutes]??0,f=n[i.seconds]??0,g=n[i.meridiem]??"am";return u||h||o?!u||h||o?u||!h||o?u||h||!o||(u=l.getFullYear(),h=l.getMonth()+1):(u=l.getFullYear(),o=1):(h=1,o=1):(u=l.getFullYear(),h=l.getMonth()+1,o=l.getDate()),u>=10&&u<100&&(u+=2e3),g=g.toLowerCase(),"pm"===g&&p<12?p+=12:"am"===g&&12===p&&(p=0),new Date(`${u}-${h}-${o} ${p}:${d}:${f}`)}function a(e){return""===e||null==e}function n(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 u(e){return e instanceof Date&&"Invalid Date"!==e.toDateString()}class h{#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)}collectPresentsThenTest(e,t,r,s){let i=[];for(const e of r)i.push(this.checkPresent(e,this.validator.getValue(e)));return!s(i)||this.checkPresent(e,t)}collectMissingsThenTest(e,t,r,s){let i=[];for(const e of r)i.push(this.checkMissing(e,this.validator.getValue(e)));return!s(i)||this.checkMissing(e,t)}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(a(t))return!1;const i=r[0]??"";let c=this.validator.getValue(i);return c=void 0===c?n(i)?parseFloat(i):null:this.validator.getSize(i,c),!a(c)&&s(this.validator.getSize(e,t),c)}compareDates(e,t,r,s){const a=this.validator.getRule(e),n=Array.isArray(a)?a.find(([e])=>"date_format"===e):null,l=n?n[1][0]:null;if(!u(t=l?c(t,l):i(t)))return!1;const h=r[0]??"";let o=this.validator.getValue(h);if(void 0===o)o=l?c(h,l):i(h);else{const e=this.validator.getRule(h),t=Array.isArray(e)?e.find(([e])=>"date_format"===e):null,r=t?t[1][0]:null;o=r?c(o,r):i(o)}return!!u(o)&&s(t.getTime(),o.getTime())}checkArray(e,t,r=[]){if(!Array.isArray(t)&&!l(t))return!1;if(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 r.includes("strict")?[!0,!1].includes(t):[!0,!1,0,1,"0","1"].includes(t)}checkDate(e,t,r){return u(i(t))}checkFile(e,t,r){return t instanceof File}checkInteger(e,t,r=[]){return r.includes("strict")||"string"!=typeof t||(t=parseFloat(t)),Number.isInteger(t)}checkNumeric(e,t,r=[]){return r.includes("strict")?"number"==typeof t:n(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(!n(t)||!n(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!a(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}checkPresentIf(e,t,r){return!this.isDependent(r)||this.checkPresent(e,t)}checkPresentUnless(e,t,r){return!!this.isDependent(r)||this.checkPresent(e,t)}checkPresentWith(e,t,r){return this.collectPresentsThenTest(e,t,r,e=>e.includes(!0))}checkPresentWithAll(e,t,r){return this.collectPresentsThenTest(e,t,r,e=>!e.includes(!1))}checkMissing(e,t,r){return void 0===t}checkMissingIf(e,t,r){return!this.isDependent(r)||this.checkMissing(e,t)}checkMissingUnless(e,t,r){return!!this.isDependent(r)||this.checkMissing(e,t)}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&&!n(t))return!1;const i=r.join(",");let[c,l,u]=i.match(/^\/(.*)\/([gimu]*)$/)??[];if(a(c))throw new Error(`Invalid regular expression pattern: ${i}`);u.includes("u")&&(l=l.replace(/\\A/g,"^").replace(/\\z/gi,"$").replace(/\\([pP])([CLMNPSZ])/g,"\\$1{$2}").replace(/\\\x\{([0-9a-f]+)\}/g,"\\u{$1}"));const h=new RegExp(l,u).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,[r[0]??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}checkDoesntContain(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 l;Object.hasOwn(this.#e,n)?l=this.#e[n]:(l=JSON.stringify(s(this.validator.getValue(n)??{})),this.#e[n]=l);const u=i.includes("ignore_case"),h=!u&&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+=l.match(new RegExp(p,"g"+(u?"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=[]){const s=["jpg","jpeg","png","gif","bmp","webp"];r.includes("allow_svg")&&s.push("svg");let i=this.checkMimes(e,t,s);return i&&"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(()=>{i=!1}),i):i}async checkDimensions(e,t,r=[]){if(!await 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(".").map(e=>parseInt(e,10));if(4!==s.length)return!1;for(const e of s)if(isNaN(e)||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(e instanceof RangeError)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 o{#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 d{constructor(e){this.validator=e}replace(e,t){return Object.entries(t).forEach(([t,r])=>e=e.replaceAll(":"+t,r)),e}replaceCaseVariants(e,t){return Object.entries(t).flatMap(([e,t])=>[[e,t],[e.toLocaleUpperCase(),t.toLocaleUpperCase()],[e.charAt(0).toLocaleUpperCase()+e.substring(1),t.charAt(0).toLocaleUpperCase()+t.substring(1)]]).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.replaceCaseVariants(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.replaceCaseVariants(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.replaceCaseVariants(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)}replacePresentIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replacePresentUnless(e,t,r,s){return this.replaceCaseVariants(this.replaceRequiredUnless(e,t,r,s),{value:this.validator.getDisplayableValue(s[0],s[1])})}replacePresentWith(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replacePresentWithAll(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.replacePresentUnless(e,t,r,s)}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.replaceCaseVariants(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)}replaceDoesntContain(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 f{static#c={};static#a={};static#n=["active_url","bail","can","current_password","encoding","enum","exclude","exclude_if","exclude_unless","exclude_with","exclude_without","exists","nullable","sometimes","unique"];static#l=["accepted","accepted_if","declined","declined_if","filled","missing","missing_if","missing_unless","missing_with","missing_with_all","present","present_if","present_unless","present_with","present_with_all","required","required_if","required_if_accepted","required_if_declined","required_unless","required_with","required_with_all","required_without","required_without_all"];#r;#u;#h;#o;#p;#d;#f;#g;#m;#k;#A;#y;static setLocale(e){p.locale(e)}static setMessages(e,t){p.setMessages(e,t)}static addChecker(e,t,r){f.#c[e]=t,r&&p.set(e,r)}static addImplicitChecker(e,t,r){f.addChecker(e,t,r),f.#l.push(e)}static addReplacer(e,t){f.#a[e]=t}static addDummyRule(e){f.#n.push(e)}constructor(e={},r={},s={},i={},c={}){this.#m=[],this.#k={},this.#A=!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 h(this),this.#f=new d(this);for(const[e,r]of Object.entries(f.#c))this.#d[t("check_"+e)]=r;for(const[e,r]of Object.entries(f.#a))this.#f[t("replace_"+e)]=r;this.#g=new o}setProperties(e={},t={},r={},i={},c={}){return this.#r=e,this.#u=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.#u=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.#A=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("function"==typeof e)return[e,[]];let t,r;if(Array.isArray(e))t=e[0]??"",r=e.slice(1);else{const s=e.indexOf(":");-1===s?(t=e,r=[]):(t=e.substring(0,s),r=function(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}(e.substring(s+1)))}return[this.normalizeRuleName(t),r]}normalizeRuleName(e){return{int:"integer",bool:"boolean"}[e]??e}async validate(){this.#d.clearCaches(),this.#g=new o;const e=[],r=new Set;for(const[e,r]of Object.entries(this.#u))for(const[e]of r)if(""!==e&&"function"!=typeof e&&"function"!=typeof this.#d[t("check_"+e)]&&!f.#n.includes(e))throw new Error(`Invalid validation rule: ${e}`);for(const[s,i]of Object.entries(this.#u)){let c=this.getValue(s);const n=e=>i.some(t=>t[0]===e);n("sometimes")&&void 0===c?r.add(s):e.push(async()=>{const e=this.#y||n("bail"),l=n("nullable");let u=!0;for(const[n,h]of i){if(""===n||"function"!=typeof n&&!f.#l.includes(n)&&(void 0===c||"string"==typeof c&&""===c.trim()||l&&null===c)){r.add(s);continue}let i,o,p;const d=(()=>{if("function"==typeof n)return n;{const e=this.#d[t("check_"+n)]??null;return null===e&&f.#n.includes(n)?()=>!0:e}})();if(null===d)throw new Error(`Invalid validation rule: ${n}`);if(i=await d.call(this.#d,s,c,h),"boolean"==typeof i&&(i={success:i}),({success:o,message:p=""}=i),!o&&(u=!1,p=a(p)?this.getMessage(s,n):p,p=this.makeReplacements(p,s,n,h),this.#g.add(s,p),e||f.#l.includes(n)))break}return u})}if(this.#A){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.#u));return this.#m=[...r],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":n(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 l=r.match(/\.(\d+)\.?/),u=null===l?-1:parseInt(l[1],10);if(-1!==u&&(e=e.replaceAll(":index",u).replaceAll(":position",u+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 Object.hasOwn(this.#p,r)?this.#p[r]:p.has(`values.${r}`)?p.get(`values.${r}`):a(t)?"empty":Array.isArray(t)?"array":"boolean"==typeof t||this.hasRule(e,"boolean")?Number(t)?"true":"false":t}getSize(e,t){return a(t)?0:this.hasRule(e,this.stringRules)?String(t).length:n(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.#u[e]??[]}hasRule(e,t){if(e=this.getPrimaryAttribute(e),t="string"==typeof t?[t]:t,!Object.hasOwn(this.#u,e))return!1;for(const r of t)if(this.#u[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(null==i||!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=h,e.ErrorBag=o,e.Lang=p,e.Replacers=d,e.Validator=f,e}({});
6
+ var quival=function(e){"use strict";const t=e=>e&&/^\d*$/.test(e)?parseInt(e):e,r=(e,t,r,s,i,c,a)=>(e>=10&&e<100&&(e+=2e3),null!==a&&("pm"===(a=a.toLowerCase())&&s<12?s+=12:"am"===a&&12===s&&(s=0)),new Date(`${e}-${t}-${r} ${s}:${i}:${c}`));function s(e){return e.replace(/[-_]/g," ").replace(/\s+/g," ").trim().replace(/(\s\w)/g,e=>e[1].toUpperCase())}function i(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function c(e,t=""){return Object.keys(e).reduce((r,s)=>{const i=t?`${t}.${s}`:s;return"object"==typeof e[s]&&null!==e[s]?Object.assign(r,c(e[s],i)):r[i]=e[s],r},{})}function a(e){if(e instanceof Date)return e;if(h(e)||"string"!=typeof e)return new Date("");let s,i,c,a,n,l,u,o;if(null!==(s=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)))[,a,c,i,,n=0,l=0,,u=0,o=null]=s.map(t);else if(null!==(s=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!==(s=e.match(/^(\d{4})(\d{2})(\d{2})\s?((\d{2})(\d{2})((\d{2}))?\s?(am|pm)?)?/i)))[,i,c,a,,n=0,l=0,,u=0,o=null]=s.map(t);else if(s=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{4})[.\/-](\d{2})[.\/-](\d{2})/i))[,n,l,,u,o=null,i,c,a]=s.map(t);else if(s=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{2})[.\/-](\d{2})[.\/-](\d{4})/i))[,n,l,,u,o=null,a,c,i]=s.map(t);else{if(!(s=e.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?/i)))return new Date(e);{const e=new Date;i=e.getFullYear(),c=e.getMonth()+1,a=e.getDate(),[,n=0,l=0,,u=0,o=null]=s.map(t)}}return r(i,c,a,n,l,u,o)}const n={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)"};function l(e,s){if(h(e))return new Date("");s=s.split("");let i="^",c={years:-1,months:-1,days:-1,hours:-1,minutes:-1,seconds:-1,meridiem:-1},a=1;for(const e of s)Object.hasOwn(n,e)?(i+=n[e],-1!==["Y","y"].indexOf(e)?c.years=a++:-1!==["m","n"].indexOf(e)?c.months=a++:-1!==["d","j"].indexOf(e)?c.days=a++:-1!==["G","g","H","h"].indexOf(e)?c.hours=a++:"i"===e?c.minutes=a++:"s"===e?c.seconds=a++:-1!==["A","a"].indexOf(e)&&(c.meridiem=a++)):i+="\\"+e;i+="$";let l=e.match(new RegExp(i));if(null===l)return new Date("");l=l.map(t);const u=new Date;let o=l[c.years],p=l[c.months],d=l[c.days],f=l[c.hours]??0,g=l[c.minutes]??0,m=l[c.seconds]??0,k=l[c.meridiem]??null;return o||p||d?!o||p||d?o||!p||d?o||p||!d||(o=u.getFullYear(),p=u.getMonth()+1):(o=u.getFullYear(),d=1):(p=1,d=1):(o=u.getFullYear(),p=u.getMonth()+1,d=u.getDate()),r(o,p,d,f,g,m,k)}function u(e){return(String(e).split(".")[1]??"").length}function h(e){return""===e||null==e}function o(e){const t=Number(e);return null!==e&&"boolean"!=typeof e&&"number"==typeof t&&!isNaN(t)}function p(e){return"[object Object]"===Object.prototype.toString.call(e)}function d(e){return e instanceof Date&&"Invalid Date"!==e.toDateString()}class f{#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)}collectAndTest(e,t,r,s,i){return!i(s.map(t=>e(t,this.validator.getValue(t))))||e(t,r)}collectRequiredsThenTest(e,t,r,s){return this.collectAndTest(this.checkRequired,e,t,r,s)}collectPresentsThenTest(e,t,r,s){return this.collectAndTest(this.checkPresent,e,t,r,s)}collectMissingsThenTest(e,t,r,s){return this.collectAndTest(this.checkMissing,e,t,r,s)}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(h(t))return!1;const i=r[0]??"";let c=this.validator.getValue(i);return c=void 0===c?o(i)?parseFloat(i):null:this.validator.getSize(i,c),!h(c)&&s(this.validator.getSize(e,t),c)}compareDates(e,t,r,s){const i=this.validator.getRule(e),c=Array.isArray(i)?i.find(([e])=>"date_format"===e):null,n=c?c[1][0]:null;if(!d(t=n?l(t,n):a(t)))return!1;const u=r[0]??"";let h=this.validator.getValue(u);if(void 0===h)h=n?l(u,n):a(u);else{const e=this.validator.getRule(u),t=Array.isArray(e)?e.find(([e])=>"date_format"===e):null,r=t?t[1][0]:null;h=r?l(h,r):a(h)}return!!d(h)&&s(t.getTime(),h.getTime())}checkArray(e,t,r=[]){if(!Array.isArray(t)&&!p(t))return!1;if(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 r.includes("strict")?[!0,!1].includes(t):[!0,!1,0,1,"0","1"].includes(t)}checkDate(e,t,r){return d(a(t))}checkFile(e,t,r){return t instanceof File}checkInteger(e,t,r=[]){return r.includes("strict")||"string"!=typeof t||(t=Number(t)),Number.isInteger(t)}checkNumeric(e,t,r=[]){return r.includes("strict")?"number"==typeof t:o(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(!o(t)||!o(r[0]))return!1;const s=Number(t),i=Number(r[0]);if(0===s&&0===i)return!1;if(0===s)return!0;if(0===i)return!1;const c=10**Math.max(u(s),u(i));return Math.round(s*c)%Math.round(i*c)===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!h(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}checkPresentIf(e,t,r){return!this.isDependent(r)||this.checkPresent(e,t)}checkPresentUnless(e,t,r){return!!this.isDependent(r)||this.checkPresent(e,t)}checkPresentWith(e,t,r){return this.collectPresentsThenTest(e,t,r,e=>e.includes(!0))}checkPresentWithAll(e,t,r){return this.collectPresentsThenTest(e,t,r,e=>!e.includes(!1))}checkMissing(e,t,r){return void 0===t}checkMissingIf(e,t,r){return!this.isDependent(r)||this.checkMissing(e,t)}checkMissingUnless(e,t,r){return!!this.isDependent(r)||this.checkMissing(e,t)}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&&!o(t))return!1;const i=r.join(",");let[c,a,n]=i.match(/^\/(.*)\/([gimu]*)$/)??[];if(h(c))throw new Error(`Invalid regular expression pattern: ${i}`);n.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,n).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,[r[0]??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("");let i="^";for(const e of s)Object.hasOwn(n,e)?i+=n[e]:i+="\\"+e;return i+="$",new RegExp(i).test(t)}checkContains(e,t,r=[]){if(!this.checkArray(e,t))return!1;const s=Array.isArray(t)?t:Object.values(t);for(const e of r)if(!s.some(t=>t==e))return!1;return!0}checkDoesntContain(e,t,r=[]){if(!this.checkArray(e,t))return!1;const s=Array.isArray(t)?t:Object.values(t);for(const e of r)if(s.some(t=>t==e))return!1;return!0}checkDistinct(e,t,r){const s=this.validator.getPrimaryAttribute(e);if(!s.includes("*"))return!0;const a=s.indexOf("*"),n=s.substring(0,a-1);let l;Object.hasOwn(this.#e,n)?l=this.#e[n]:(l=JSON.stringify(c(this.validator.getValue(n)??{})),this.#e[n]=l);const u=r.includes("ignore_case"),h=!u&&r.includes("strict"),o=i(String(t));let p=`"${i(s.substring(a)).replaceAll("\\*",'[^."]+')}":`,d=0;return p+=h?"string"==typeof t?`"${o}"`:`${o}`:`(${o}|"${o}")`,p+="[,}]+",d+=l.match(new RegExp(p,"g"+(u?"i":"")))?.length??0,1===d}checkInArray(e,t,r){const s=this.validator.getPrimaryAttribute(r[0]);if(!s.includes("*"))return!1;const i=this.validator.getValue(s.split(".*")[0])??{};return Object.values(c(i)).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=[]){const s=["jpg","jpeg","png","gif","bmp","webp"];r.includes("allow_svg")&&s.push("svg");let i=this.checkMimes(e,t,s);return i&&"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(()=>{i=!1}),i):i}async checkDimensions(e,t,r=[]){if(!await 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));s[t]=e/i}else s[t]=parseFloat(r)}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(".").map(e=>parseInt(e,10));if(4!==s.length)return!1;for(const e of s)if(isNaN(e)||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(e instanceof RangeError)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}$/i.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 g{#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 m{static#s;static#i={};static locale(e){this.#s=e}static setMessages(e,t){this.#i[e]=c(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){p(t)?Object.assign(this.#i[this.#s],c(t,e)):"string"==typeof t&&(this.#i[this.#s][e]=t)}}class k{constructor(e){this.validator=e}replace(e,t){return Object.entries(t).forEach(([t,r])=>e=e.replaceAll(":"+t,r)),e}replaceCaseVariants(e,t){return Object.entries(t).flatMap(([e,t])=>[[e,t=String(t)],[e.toLocaleUpperCase(),t.toLocaleUpperCase()],[e.charAt(0).toLocaleUpperCase()+e.substring(1),t.charAt(0).toLocaleUpperCase()+t.substring(1)]]).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.replaceCaseVariants(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.replaceCaseVariants(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.replaceCaseVariants(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)}replacePresentIf(e,t,r,s){return this.replaceAcceptedIf(e,t,r,s)}replacePresentUnless(e,t,r,s){return this.replaceCaseVariants(this.replaceRequiredUnless(e,t,r,s),{value:this.validator.getDisplayableValue(s[0],s[1])})}replacePresentWith(e,t,r,s){return this.replaceRequiredWith(e,t,r,s)}replacePresentWithAll(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.replacePresentUnless(e,t,r,s)}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.replaceCaseVariants(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:void 0===i?this.validator.getDisplayableAttribute(s[0]):this.validator.getSize(s[0],i)})}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)}replaceDoesntContain(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 A{static#c={};static#a={};static#n=["active_url","bail","can","current_password","encoding","enum","exclude","exclude_if","exclude_unless","exclude_with","exclude_without","exists","nullable","sometimes","unique"];static#l=["accepted","accepted_if","declined","declined_if","filled","missing","missing_if","missing_unless","missing_with","missing_with_all","present","present_if","present_unless","present_with","present_with_all","required","required_if","required_if_accepted","required_if_declined","required_unless","required_with","required_with_all","required_without","required_without_all"];#r;#u;#h;#o;#p;#d;#f;#g;#m;#k;#A;#y;static setLocale(e){m.locale(e)}static setMessages(e,t){m.setMessages(e,t)}static addChecker(e,t,r){A.#c[e]=t,r&&m.set(e,r)}static addImplicitChecker(e,t,r){A.addChecker(e,t,r),A.#l.push(e)}static addReplacer(e,t){A.#a[e]=t}static addDummyRule(e){A.#n.push(e)}constructor(e={},t={},r={},i={},c={}){this.#m=[],this.#k={},this.#A=!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,t,r,i,c),this.#d=new f(this),this.#f=new k(this);for(const[e,t]of Object.entries(A.#c))this.#d[s("check_"+e)]=t;for(const[e,t]of Object.entries(A.#a))this.#f[s("replace_"+e)]=t;this.#g=new g}setProperties(e={},t={},r={},s={},i={}){return this.#r=e,this.#u=this.parseRules(t),this.#h=r,this.#o=s,this.#p=c(i),this}setData(e){return this.#r=e,this}setRules(e){return this.#u=this.parseRules(e),this}setCustomMessages(e){return this.#h=e,this}setCustomAttributes(e){return this.#o=e,this}setCustomValues(e){return this.#p=c(e),this}addImplicitAttribute(e,t){return this.#k[e]=t,this}stopOnFirstFailure(e=!0){return this.#A=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)||p(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("function"==typeof e)return[e,[]];let t,r;if(Array.isArray(e))t=e[0]??"",r=e.slice(1);else{const s=e.indexOf(":");-1===s?(t=e,r=[]):(t=e.substring(0,s),r=function(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}(e.substring(s+1)))}return[this.normalizeRuleName(t),r]}normalizeRuleName(e){return{int:"integer",bool:"boolean"}[e]??e}async validate(){this.#d.clearCaches(),this.#g=new g;const e=[],t=new Set;for(const[e,t]of Object.entries(this.#u))for(const[e]of t)if(""!==e&&"function"!=typeof e&&"function"!=typeof this.#d[s("check_"+e)]&&!A.#n.includes(e))throw new Error(`Invalid validation rule: ${e}`);for(const[r,i]of Object.entries(this.#u)){let c=this.getValue(r);const a=e=>i.some(t=>t[0]===e);a("sometimes")&&void 0===c?t.add(r):e.push(async()=>{const e=this.#y||a("bail"),n=a("nullable");let l=!0;for(const[a,u]of i){if(""===a||"function"!=typeof a&&!A.#l.includes(a)&&(void 0===c||"string"==typeof c&&""===c.trim()||n&&null===c)){t.add(r);continue}let i,o,p;const d=(()=>{if("function"==typeof a)return a;{const e=this.#d[s("check_"+a)]??null;return null===e&&A.#n.includes(a)?()=>!0:e}})();if(null===d)throw new Error(`Invalid validation rule: ${a}`);if(i=await d.call(this.#d,r,c,u),"boolean"==typeof i&&(i={success:i}),({success:o,message:p=""}=i),!o&&(l=!1,p=h(p)?this.getMessage(r,a):p,p=this.makeReplacements(p,r,a,u),this.#g.add(r,p),e||A.#l.includes(a)))break}return l})}if(this.#A){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.#u));return this.#m=[...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)||p(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":o(r)||this.hasRule(e,this.numericRules)?i+=".numeric":i+=".string"),s=m.get(i)}return s??`validation.${t}`}makeReplacements(e,t,r,i){const c=this.getDisplayableAttribute(t),a=this.getValue(t),n={attribute:c,ATTRIBUTE:c.toLocaleUpperCase(),Attribute:c.charAt(0).toLocaleUpperCase()+c.substring(1),input:this.getDisplayableValue(t,a)};for(const[t,r]of Object.entries(n))e=e.replaceAll(":"+t,r);const l=t.match(/\.(\d+)\.?/),u=null===l?-1:parseInt(l[1],10);if(-1!==u&&(e=e.replaceAll(":index",u).replaceAll(":position",u+1)),"string"==typeof r){const c=this.#f[s("replace_"+r)]??null;c&&(e=c.call(this.#f,e,t,r,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(m.has(`attributes.${r}`))return m.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 Object.hasOwn(this.#p,r)?this.#p[r]:m.has(`values.${r}`)?m.get(`values.${r}`):h(t)?"empty":Array.isArray(t)?"array":"boolean"==typeof t||this.hasRule(e,"boolean")?Number(t)?"true":"false":t}getSize(e,t){return h(t)?0:this.hasRule(e,this.stringRules)?String(t).length:o(t)&&this.hasRule(e,this.numericRules)?parseFloat("string"==typeof t?t.trim():t):t instanceof File?t.size/1024:p(t)?Object.keys(t).length:Object.hasOwn(t,"length")?t.length:t}getRule(e){return e=this.getPrimaryAttribute(e),this.#u[e]??[]}hasRule(e,t){if(e=this.getPrimaryAttribute(e),t="string"==typeof t?[t]:t,!Object.hasOwn(this.#u,e))return!1;for(const r of t)if(this.#u[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(null==i||!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=f,e.ErrorBag=g,e.Lang=m,e.Replacers=k,e.Validator=A,e}({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quival",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "Data validation à la Laravel Validation",
5
5
  "author": "Mohd Hafizuddin M Marzuki <hafizuddin_83@yahoo.com>",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  "devDependencies": {
26
26
  "@rollup/plugin-node-resolve": "^16.0.1",
27
27
  "@rollup/plugin-swc": "^0.4.0",
28
- "@rollup/plugin-terser": "^0.4.1",
28
+ "@rollup/plugin-terser": "^1.0.0",
29
29
  "mocha": "^11.1.0",
30
30
  "prettier": "^3.2.5",
31
31
  "rollup": "^4.6.1",
package/src/Checkers.js CHANGED
@@ -1,4 +1,16 @@
1
- import { escapeRegExp, flattenObject, isDigits, isEmpty, isNumeric, isPlainObject, isValidDate, parseDate, parseDateByFormat } from './helpers.js';
1
+ import {
2
+ DATE_FORMAT_PATTERNS,
3
+ escapeRegExp,
4
+ flattenObject,
5
+ getDecimalPlaces,
6
+ isDigits,
7
+ isEmpty,
8
+ isNumeric,
9
+ isPlainObject,
10
+ isValidDate,
11
+ parseDate,
12
+ parseDateByFormat,
13
+ } from './helpers.js';
2
14
 
3
15
  export default class Checkers {
4
16
  validator;
@@ -21,46 +33,22 @@ export default class Checkers {
21
33
  return parameters.slice(1).some((value) => value == other);
22
34
  }
23
35
 
24
- collectRequiredsThenTest(attribute, value, parameters, callback) {
25
- let result = [];
26
-
27
- for (const other of parameters) {
28
- result.push(this.checkRequired(other, this.validator.getValue(other)));
29
- }
36
+ collectAndTest(checker, attribute, value, parameters, callback) {
37
+ const result = parameters.map((other) => checker(other, this.validator.getValue(other)));
30
38
 
31
- if (callback(result)) {
32
- return this.checkRequired(attribute, value);
33
- }
39
+ return callback(result) ? checker(attribute, value) : true;
40
+ }
34
41
 
35
- return true;
42
+ collectRequiredsThenTest(attribute, value, parameters, callback) {
43
+ return this.collectAndTest(this.checkRequired, attribute, value, parameters, callback);
36
44
  }
37
45
 
38
46
  collectPresentsThenTest(attribute, value, parameters, callback) {
39
- let result = [];
40
-
41
- for (const other of parameters) {
42
- result.push(this.checkPresent(other, this.validator.getValue(other)));
43
- }
44
-
45
- if (callback(result)) {
46
- return this.checkPresent(attribute, value);
47
- }
48
-
49
- return true;
47
+ return this.collectAndTest(this.checkPresent, attribute, value, parameters, callback);
50
48
  }
51
49
 
52
50
  collectMissingsThenTest(attribute, value, parameters, callback) {
53
- let result = [];
54
-
55
- for (const other of parameters) {
56
- result.push(this.checkMissing(other, this.validator.getValue(other)));
57
- }
58
-
59
- if (callback(result)) {
60
- return this.checkMissing(attribute, value);
61
- }
62
-
63
- return true;
51
+ return this.collectAndTest(this.checkMissing, attribute, value, parameters, callback);
64
52
  }
65
53
 
66
54
  testStringUsingRegex(attribute, value, asciiRegex, unicodeRegex, isAscii = false) {
@@ -172,7 +160,7 @@ export default class Checkers {
172
160
 
173
161
  checkInteger(attribute, value, parameters = []) {
174
162
  if (!parameters.includes('strict') && typeof value === 'string') {
175
- value = parseFloat(value);
163
+ value = Number(value);
176
164
  }
177
165
 
178
166
  return Number.isInteger(value);
@@ -210,8 +198,8 @@ export default class Checkers {
210
198
  return false;
211
199
  }
212
200
 
213
- const numerator = parseInt(value, 10);
214
- const denominator = parseInt(parameters[0], 10);
201
+ const numerator = Number(value);
202
+ const denominator = Number(parameters[0]);
215
203
 
216
204
  if (numerator === 0 && denominator === 0) {
217
205
  return false;
@@ -221,7 +209,10 @@ export default class Checkers {
221
209
  return false;
222
210
  }
223
211
 
224
- return numerator % denominator === 0;
212
+ const decimalPlaces = Math.max(getDecimalPlaces(numerator), getDecimalPlaces(denominator));
213
+ const factor = 10 ** decimalPlaces;
214
+
215
+ return Math.round(numerator * factor) % Math.round(denominator * factor) === 0;
225
216
  }
226
217
 
227
218
  // Agreement
@@ -615,28 +606,11 @@ export default class Checkers {
615
606
  checkDateFormat(attribute, value, parameters) {
616
607
  const format = parameters[0].split('');
617
608
 
618
- const formats = {
619
- Y: '(\\d{4})',
620
- y: '(\\d{2})',
621
- m: '(\\d{2})',
622
- n: '([1-9]\\d?)',
623
- d: '(\\d{2})',
624
- j: '([1-9]\\d?)',
625
- G: '([1-9]\\d?)',
626
- g: '([1-9]\\d?)',
627
- H: '(\\d{2})',
628
- h: '(\\d{2})',
629
- i: '(\\d{2})',
630
- s: '(\\d{2})',
631
- A: '(AM|PM)',
632
- a: '(am|pm)',
633
- };
634
-
635
609
  let pattern = '^';
636
610
 
637
611
  for (const char of format) {
638
- if (Object.hasOwn(formats, char)) {
639
- pattern += formats[char];
612
+ if (Object.hasOwn(DATE_FORMAT_PATTERNS, char)) {
613
+ pattern += DATE_FORMAT_PATTERNS[char];
640
614
  } else {
641
615
  pattern += '\\' + char;
642
616
  }
@@ -653,8 +627,10 @@ export default class Checkers {
653
627
  return false;
654
628
  }
655
629
 
630
+ const values = Array.isArray(value) ? value : Object.values(value);
631
+
656
632
  for (const parameter of parameters) {
657
- if (!value.includes(parameter)) {
633
+ if (!values.some((item) => item == parameter)) {
658
634
  return false;
659
635
  }
660
636
  }
@@ -667,8 +643,10 @@ export default class Checkers {
667
643
  return false;
668
644
  }
669
645
 
646
+ const values = Array.isArray(value) ? value : Object.values(value);
647
+
670
648
  for (const parameter of parameters) {
671
- if (value.includes(parameter)) {
649
+ if (values.some((item) => item == parameter)) {
672
650
  return false;
673
651
  }
674
652
  }
@@ -823,11 +801,11 @@ export default class Checkers {
823
801
  const [key, value] = parameter.split('=', 2);
824
802
 
825
803
  if (key === 'ratio' && value.includes('/')) {
826
- const [numerator, denominator] = value.split('/', 2).map((part) => parseFloat(part, 10));
804
+ const [numerator, denominator] = value.split('/', 2).map((part) => parseFloat(part));
827
805
 
828
806
  constraints[key] = numerator / denominator;
829
807
  } else {
830
- constraints[key] = parseFloat(value, 10);
808
+ constraints[key] = parseFloat(value);
831
809
  }
832
810
  }
833
811
 
@@ -985,7 +963,7 @@ export default class Checkers {
985
963
  }
986
964
 
987
965
  checkUlid(attribute, value, parameters) {
988
- return /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/.test(value);
966
+ return /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i.test(value);
989
967
  }
990
968
 
991
969
  checkUuid(attribute, value, parameters) {
package/src/Replacers.js CHANGED
@@ -13,11 +13,15 @@ export default class Replacers {
13
13
 
14
14
  replaceCaseVariants(message, data) {
15
15
  Object.entries(data)
16
- .flatMap(([key, value]) => [
17
- [key, value],
18
- [key.toLocaleUpperCase(), value.toLocaleUpperCase()],
19
- [key.charAt(0).toLocaleUpperCase() + key.substring(1), value.charAt(0).toLocaleUpperCase() + value.substring(1)],
20
- ])
16
+ .flatMap(([key, value]) => {
17
+ value = String(value);
18
+
19
+ return [
20
+ [key, value],
21
+ [key.toLocaleUpperCase(), value.toLocaleUpperCase()],
22
+ [key.charAt(0).toLocaleUpperCase() + key.substring(1), value.charAt(0).toLocaleUpperCase() + value.substring(1)],
23
+ ];
24
+ })
21
25
  .forEach(([key, value]) => (message = message.replaceAll(':' + key, value)));
22
26
 
23
27
  return message;
@@ -221,7 +225,7 @@ export default class Replacers {
221
225
  const value = this.validator.getValue(parameters[0]);
222
226
 
223
227
  return this.replace(message, {
224
- value: value ? this.validator.getSize(parameters[0], value) : this.validator.getDisplayableAttribute(parameters[0]),
228
+ value: typeof value === 'undefined' ? this.validator.getDisplayableAttribute(parameters[0]) : this.validator.getSize(parameters[0], value),
225
229
  });
226
230
  }
227
231
 
package/src/Validator.js CHANGED
@@ -510,7 +510,7 @@ export default class Validator {
510
510
  } else if (this.hasRule(attribute, this.stringRules)) {
511
511
  return String(value).length;
512
512
  } else if (isNumeric(value) && this.hasRule(attribute, this.numericRules)) {
513
- return parseFloat(typeof value === 'string' ? value.trim() : value, 10);
513
+ return parseFloat(typeof value === 'string' ? value.trim() : value);
514
514
  } else if (value instanceof File) {
515
515
  return value.size / 1024;
516
516
  } else if (isPlainObject(value)) {
package/src/helpers.js CHANGED
@@ -1,3 +1,23 @@
1
+ const castToIntegers = (value) => (value && /^\d*$/.test(value) ? parseInt(value) : value);
2
+
3
+ const buildDate = (years, months, days, hours, minutes, seconds, meridiem) => {
4
+ if (years >= 10 && years < 100) {
5
+ years += 2000;
6
+ }
7
+
8
+ if (meridiem !== null) {
9
+ meridiem = meridiem.toLowerCase();
10
+
11
+ if (meridiem === 'pm' && hours < 12) {
12
+ hours += 12;
13
+ } else if (meridiem === 'am' && hours === 12) {
14
+ hours = 0;
15
+ }
16
+ }
17
+
18
+ return new Date(`${years}-${months}-${days} ${hours}:${minutes}:${seconds}`);
19
+ };
20
+
1
21
  export function toCamelCase(string) {
2
22
  return string
3
23
  .replace(/[-_]/g, ' ')
@@ -99,19 +119,17 @@ export function parseDate(value) {
99
119
 
100
120
  let match, years, months, days, hours, minutes, seconds, meridiem;
101
121
 
102
- const castToIntegers = (value) => (value && /^\d*$/.test(value) ? parseInt(value) : value);
103
-
104
122
  if ((match = value.match(/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{2,4})\s?((\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?)?/i)) !== null) {
105
- [, days, months, years, , hours = 0, minutes = 0, , seconds = 0, meridiem = 'am'] = match.map(castToIntegers);
123
+ [, days, months, years, , hours = 0, minutes = 0, , seconds = 0, meridiem = null] = match.map(castToIntegers);
106
124
  } else if (
107
125
  (match = value.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 ||
108
126
  (match = value.match(/^(\d{4})(\d{2})(\d{2})\s?((\d{2})(\d{2})((\d{2}))?\s?(am|pm)?)?/i)) !== null
109
127
  ) {
110
- [, years, months, days, , hours = 0, minutes = 0, , seconds = 0, meridiem = 'am'] = match.map(castToIntegers);
128
+ [, years, months, days, , hours = 0, minutes = 0, , seconds = 0, meridiem = null] = match.map(castToIntegers);
111
129
  } else if ((match = value.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{4})[.\/-](\d{2})[.\/-](\d{2})/i))) {
112
- [, hours, minutes, , seconds, meridiem = 'am', years, months, days] = match.map(castToIntegers);
130
+ [, hours, minutes, , seconds, meridiem = null, years, months, days] = match.map(castToIntegers);
113
131
  } else if ((match = value.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?\s?(\d{2})[.\/-](\d{2})[.\/-](\d{4})/i))) {
114
- [, hours, minutes, , seconds, meridiem = 'am', days, months, years] = match.map(castToIntegers);
132
+ [, hours, minutes, , seconds, meridiem = null, days, months, years] = match.map(castToIntegers);
115
133
  } else if ((match = value.match(/(\d{1,2}):(\d{1,2})(:(\d{1,2}))?\s?(am|pm)?/i))) {
116
134
  const current = new Date();
117
135
 
@@ -119,26 +137,31 @@ export function parseDate(value) {
119
137
  months = current.getMonth() + 1;
120
138
  days = current.getDate();
121
139
 
122
- [, hours = 0, minutes = 0, , seconds = 0, meridiem = 'am'] = match.map(castToIntegers);
140
+ [, hours = 0, minutes = 0, , seconds = 0, meridiem = null] = match.map(castToIntegers);
123
141
  } else {
124
142
  return new Date(value);
125
143
  }
126
144
 
127
- if (years >= 10 && years < 100) {
128
- years += 2000;
129
- }
130
-
131
- meridiem = meridiem.toLowerCase();
132
-
133
- if (meridiem === 'pm' && hours < 12) {
134
- hours += 12;
135
- } else if (meridiem === 'am' && hours === 12) {
136
- hours = 0;
137
- }
138
-
139
- return new Date(`${years}-${months}-${days} ${hours}:${minutes}:${seconds}`);
145
+ return buildDate(years, months, days, hours, minutes, seconds, meridiem);
140
146
  }
141
147
 
148
+ export const DATE_FORMAT_PATTERNS = {
149
+ Y: '(\\d{4})',
150
+ y: '(\\d{2})',
151
+ m: '(\\d{2})',
152
+ n: '([1-9]\\d?)',
153
+ d: '(\\d{2})',
154
+ j: '([1-9]\\d?)',
155
+ G: '([1-9]\\d?)',
156
+ g: '([1-9]\\d?)',
157
+ H: '(\\d{2})',
158
+ h: '(\\d{2})',
159
+ i: '(\\d{2})',
160
+ s: '(\\d{2})',
161
+ A: '(AM|PM)',
162
+ a: '(am|pm)',
163
+ };
164
+
142
165
  export function parseDateByFormat(value, format) {
143
166
  if (isEmpty(value)) {
144
167
  return new Date('');
@@ -146,23 +169,6 @@ export function parseDateByFormat(value, format) {
146
169
 
147
170
  format = format.split('');
148
171
 
149
- const formats = {
150
- Y: '(\\d{4})',
151
- y: '(\\d{2})',
152
- m: '(\\d{2})',
153
- n: '([1-9]\\d?)',
154
- d: '(\\d{2})',
155
- j: '([1-9]\\d?)',
156
- G: '([1-9]\\d?)',
157
- g: '([1-9]\\d?)',
158
- H: '(\\d{2})',
159
- h: '(\\d{2})',
160
- i: '(\\d{2})',
161
- s: '(\\d{2})',
162
- A: '(AM|PM)',
163
- a: '(am|pm)',
164
- };
165
-
166
172
  let pattern = '^';
167
173
  let indices = {
168
174
  years: -1,
@@ -177,8 +183,8 @@ export function parseDateByFormat(value, format) {
177
183
  let index = 1;
178
184
 
179
185
  for (const char of format) {
180
- if (Object.hasOwn(formats, char)) {
181
- pattern += formats[char];
186
+ if (Object.hasOwn(DATE_FORMAT_PATTERNS, char)) {
187
+ pattern += DATE_FORMAT_PATTERNS[char];
182
188
 
183
189
  if (['Y', 'y'].indexOf(char) !== -1) {
184
190
  indices.years = index++;
@@ -208,7 +214,7 @@ export function parseDateByFormat(value, format) {
208
214
  return new Date('');
209
215
  }
210
216
 
211
- match = match.map((value) => (value && /^\d*$/.test(value) ? parseInt(value) : value));
217
+ match = match.map(castToIntegers);
212
218
 
213
219
  const current = new Date();
214
220
 
@@ -218,7 +224,7 @@ export function parseDateByFormat(value, format) {
218
224
  let hours = match[indices.hours] ?? 0;
219
225
  let minutes = match[indices.minutes] ?? 0;
220
226
  let seconds = match[indices.seconds] ?? 0;
221
- let meridiem = match[indices.meridiem] ?? 'am';
227
+ let meridiem = match[indices.meridiem] ?? null;
222
228
 
223
229
  if (!years && !months && !days) {
224
230
  years = current.getFullYear();
@@ -235,19 +241,11 @@ export function parseDateByFormat(value, format) {
235
241
  months = current.getMonth() + 1;
236
242
  }
237
243
 
238
- if (years >= 10 && years < 100) {
239
- years = years + 2000;
240
- }
241
-
242
- meridiem = meridiem.toLowerCase();
243
-
244
- if (meridiem === 'pm' && hours < 12) {
245
- hours += 12;
246
- } else if (meridiem === 'am' && hours === 12) {
247
- hours = 0;
248
- }
244
+ return buildDate(years, months, days, hours, minutes, seconds, meridiem);
245
+ }
249
246
 
250
- return new Date(`${years}-${months}-${days} ${hours}:${minutes}:${seconds}`);
247
+ export function getDecimalPlaces(value) {
248
+ return (String(value).split('.')[1] ?? '').length;
251
249
  }
252
250
 
253
251
  export function isDigits(value) {
package/test/helpers.js CHANGED
@@ -137,6 +137,11 @@ describe('Helpers', () => {
137
137
  assert.deepEqual(parseDate('2023-08-11 12:30:00 am'), date4);
138
138
  assert.deepEqual(parseDate('11-08-2023 12:30:00 am'), date4);
139
139
  assert.deepEqual(parseDate('12:30:00 am 2023-08-11'), date4);
140
+
141
+ const date5 = new Date('2026/01/03 12:10:17');
142
+ assert.deepEqual(parseDate('2026-01-03 12:10:17'), date5);
143
+ assert.deepEqual(parseDate('03-01-2026 12:10:17'), date5);
144
+ assert.deepEqual(parseDate('12:10:17 2026-01-03'), date5);
140
145
  });
141
146
 
142
147
  it('parseDateByFormat', () => {
@@ -157,6 +162,9 @@ describe('Helpers', () => {
157
162
 
158
163
  const date4 = new Date('2023/08/11 00:30:00');
159
164
  assert.deepEqual(parseDateByFormat('08-11-2023 12:30:00 am', 'm-d-Y H:i:s a'), date4);
165
+
166
+ const date5 = new Date('2026/01/03 12:10:17');
167
+ assert.deepEqual(parseDateByFormat('01-03-2026 12:10:17', 'm-d-Y H:i:s'), date5);
160
168
  });
161
169
 
162
170
  it('isDigits', () => {
@@ -598,17 +598,28 @@ describe('Validation', () => {
598
598
  it(`Passes when the field contains required values`, async () => {
599
599
  const validator = new Validator({ field: ['abc', 'def', 'ghi'] }, rules);
600
600
  assert(await validator.passes());
601
+
602
+ validator.setData({ field: { x: 'abc', y: 'def', z: 'ghi' } });
603
+ assert(await validator.passes());
601
604
  });
602
605
 
603
606
  it(`Fails when the field does not contain required values`, async () => {
604
607
  const validator = new Validator({ field: ['def', 'ghi'] }, rules);
605
608
  assert(await validator.fails());
609
+
610
+ validator.setData({ field: { y: 'def', z: 'ghi' } });
611
+ assert(await validator.fails());
606
612
  });
607
613
 
608
614
  it(`Fails when the field is not an array`, async () => {
609
615
  const validator = new Validator({ field: 'abc' }, rules);
610
616
  assert(await validator.fails());
611
617
  });
618
+
619
+ it(`Passes when the field contains numeric values matching string parameters`, async () => {
620
+ const validator = new Validator({ field: [1, 2, 3] }, { field: 'contains:1,2' });
621
+ assert(await validator.passes());
622
+ });
612
623
  });
613
624
 
614
625
  describe(`Rule 'date'`, () => {
@@ -917,17 +928,28 @@ describe('Validation', () => {
917
928
  it(`Passes when the field does not contain provided values`, async () => {
918
929
  const validator = new Validator({ field: ['ghi', 'jkl', 'mno'] }, rules);
919
930
  assert(await validator.passes());
931
+
932
+ validator.setData({ field: { x: 'ghi', y: 'jkl', z: 'mno' } });
933
+ assert(await validator.passes());
920
934
  });
921
935
 
922
936
  it(`Fails when the field contains provided values`, async () => {
923
937
  const validator = new Validator({ field: ['def', 'ghi'] }, rules);
924
938
  assert(await validator.fails());
939
+
940
+ validator.setData({ field: { y: 'def', z: 'ghi' } });
941
+ assert(await validator.fails());
925
942
  });
926
943
 
927
944
  it(`Fails when the field is not an array`, async () => {
928
945
  const validator = new Validator({ field: 'abc' }, rules);
929
946
  assert(await validator.fails());
930
947
  });
948
+
949
+ it(`Fails when the field contains numeric values matching string parameters`, async () => {
950
+ const validator = new Validator({ field: [1, 2, 3] }, { field: 'doesnt_contain:1,9' });
951
+ assert(await validator.fails());
952
+ });
931
953
  });
932
954
 
933
955
  describe(`Rule 'doesnt_end_with'`, () => {
@@ -1476,6 +1498,12 @@ describe('Validation', () => {
1476
1498
  validator.setData({ field: 'abc' });
1477
1499
  assert(await validator.fails());
1478
1500
 
1501
+ validator.setData({ field: 'abc123' });
1502
+ assert(await validator.fails());
1503
+
1504
+ validator.setData({ field: '123abc' });
1505
+ assert(await validator.fails());
1506
+
1479
1507
  validator.setData({ field: [1, 2, 3] });
1480
1508
  assert(await validator.fails());
1481
1509
  });
@@ -2304,6 +2332,19 @@ describe('Validation', () => {
2304
2332
  validator.setProperties({ field: 58 }, { field: 'multiple_of:11' });
2305
2333
  assert(await validator.fails());
2306
2334
  });
2335
+
2336
+ it(`Passes when decimal value is multiple of decimal parameter`, async () => {
2337
+ const validator = new Validator({ field: 0.3 }, { field: 'multiple_of:0.1' });
2338
+ assert(await validator.passes());
2339
+
2340
+ validator.setProperties({ field: 5 }, { field: 'multiple_of:2.5' });
2341
+ assert(await validator.passes());
2342
+ });
2343
+
2344
+ it(`Fails when decimal value is not multiple of decimal parameter`, async () => {
2345
+ const validator = new Validator({ field: 0.75 }, { field: 'multiple_of:0.5' });
2346
+ assert(await validator.fails());
2347
+ });
2307
2348
  });
2308
2349
 
2309
2350
  describe(`Rule 'not_in'`, () => {
@@ -3285,6 +3326,11 @@ describe('Validation', () => {
3285
3326
  assert(await validator.passes());
3286
3327
  });
3287
3328
 
3329
+ it(`Passes when the field is a valid lowercase ULID`, async () => {
3330
+ const validator = new Validator({ field: '01gzpcvrpr6k3kqw5b9esb8ph3' }, rules);
3331
+ assert(await validator.passes());
3332
+ });
3333
+
3288
3334
  it(`Fails when the field is an invalid ULID`, async () => {
3289
3335
  const validator = new Validator({ field: '01GZPCVRPR6K3KOW5B9ESB8PH3' }, rules);
3290
3336
  assert(await validator.fails());