@rbl-dev/validator-ts 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/Validator.js +105 -2
  2. package/dist/contracts/Validation.d.ts +3 -0
  3. package/dist/index.d.ts +17 -0
  4. package/dist/index.js +17 -0
  5. package/dist/rules/AfterDateRule.d.ts +6 -0
  6. package/dist/rules/AfterDateRule.js +20 -0
  7. package/dist/rules/AlphaNumRule.d.ts +4 -0
  8. package/dist/rules/AlphaNumRule.js +12 -0
  9. package/dist/rules/AlphaRule.d.ts +4 -0
  10. package/dist/rules/AlphaRule.js +11 -0
  11. package/dist/rules/ArrayRule.d.ts +4 -0
  12. package/dist/rules/ArrayRule.js +11 -0
  13. package/dist/rules/BeforeDateRule.d.ts +6 -0
  14. package/dist/rules/BeforeDateRule.js +20 -0
  15. package/dist/rules/BetweenRule.d.ts +7 -0
  16. package/dist/rules/BetweenRule.js +34 -0
  17. package/dist/rules/BooleanRule.d.ts +4 -0
  18. package/dist/rules/BooleanRule.js +12 -0
  19. package/dist/rules/ConfirmedRule.d.ts +6 -0
  20. package/dist/rules/ConfirmedRule.js +18 -0
  21. package/dist/rules/DateFormatRule.d.ts +6 -0
  22. package/dist/rules/DateFormatRule.js +29 -0
  23. package/dist/rules/DateRule.d.ts +4 -0
  24. package/dist/rules/DateRule.js +19 -0
  25. package/dist/rules/ExistsRule.d.ts +8 -0
  26. package/dist/rules/ExistsRule.js +20 -0
  27. package/dist/rules/ImageRule.d.ts +4 -0
  28. package/dist/rules/ImageRule.js +32 -0
  29. package/dist/rules/IntegerRule.d.ts +4 -0
  30. package/dist/rules/IntegerRule.js +13 -0
  31. package/dist/rules/MimesRule.d.ts +6 -0
  32. package/dist/rules/MimesRule.js +29 -0
  33. package/dist/rules/NullableRule.d.ts +4 -0
  34. package/dist/rules/NullableRule.js +7 -0
  35. package/dist/rules/NumericRule.d.ts +4 -0
  36. package/dist/rules/NumericRule.js +16 -0
  37. package/dist/rules/RegexRule.d.ts +6 -0
  38. package/dist/rules/RegexRule.js +16 -0
  39. package/dist/rules/RequiredIfRule.d.ts +9 -0
  40. package/dist/rules/RequiredIfRule.js +25 -0
  41. package/dist/rules/RequiredUnlessRule.d.ts +9 -0
  42. package/dist/rules/RequiredUnlessRule.js +24 -0
  43. package/dist/rules/SameRule.d.ts +7 -0
  44. package/dist/rules/SameRule.js +20 -0
  45. package/dist/rules/SometimesRule.d.ts +4 -0
  46. package/dist/rules/SometimesRule.js +7 -0
  47. package/dist/rules/StringRule.d.ts +4 -0
  48. package/dist/rules/StringRule.js +11 -0
  49. package/dist/rules/UniqueRule.d.ts +8 -0
  50. package/dist/rules/UniqueRule.js +20 -0
  51. package/package.json +1 -1
package/dist/Validator.js CHANGED
@@ -1,10 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Validator = void 0;
4
+ const AfterDateRule_js_1 = require("./rules/AfterDateRule.js");
5
+ const AlphaNumRule_js_1 = require("./rules/AlphaNumRule.js");
6
+ const AlphaRule_js_1 = require("./rules/AlphaRule.js");
7
+ const ArrayRule_js_1 = require("./rules/ArrayRule.js");
8
+ const BeforeDateRule_js_1 = require("./rules/BeforeDateRule.js");
9
+ const BetweenRule_js_1 = require("./rules/BetweenRule.js");
10
+ const BooleanRule_js_1 = require("./rules/BooleanRule.js");
11
+ const ConfirmedRule_js_1 = require("./rules/ConfirmedRule.js");
12
+ const DateFormatRule_js_1 = require("./rules/DateFormatRule.js");
13
+ const DateRule_js_1 = require("./rules/DateRule.js");
4
14
  const EmailRule_js_1 = require("./rules/EmailRule.js");
15
+ const ImageRule_js_1 = require("./rules/ImageRule.js");
16
+ const IntegerRule_js_1 = require("./rules/IntegerRule.js");
5
17
  const MaxRule_js_1 = require("./rules/MaxRule.js");
18
+ const MimesRule_js_1 = require("./rules/MimesRule.js");
6
19
  const MinRule_js_1 = require("./rules/MinRule.js");
20
+ const NullableRule_js_1 = require("./rules/NullableRule.js");
21
+ const NumericRule_js_1 = require("./rules/NumericRule.js");
22
+ const RegexRule_js_1 = require("./rules/RegexRule.js");
23
+ const RequiredIfRule_js_1 = require("./rules/RequiredIfRule.js");
7
24
  const RequiredRule_js_1 = require("./rules/RequiredRule.js");
25
+ const RequiredUnlessRule_js_1 = require("./rules/RequiredUnlessRule.js");
26
+ const SameRule_js_1 = require("./rules/SameRule.js");
27
+ const SometimesRule_js_1 = require("./rules/SometimesRule.js");
28
+ const StringRule_js_1 = require("./rules/StringRule.js");
8
29
  const data_1 = require("./utils/data");
9
30
  class Validator {
10
31
  data;
@@ -86,10 +107,18 @@ class Validator {
86
107
  this.errors = {};
87
108
  const validationPromises = [];
88
109
  for (const [attribute, attributeRules] of Object.entries(this.normalizedRules)) {
89
- // 🚀 Fix: Dynamically locate deeply nested object keys using dot notation
90
110
  const value = (0, data_1.dataGet)(this.data, attribute);
91
111
  const isEmpty = value === undefined || value === null || value === '';
92
- // We handle bails in an isolation chain block per field
112
+ const hasSometimes = attributeRules.includes('sometimes');
113
+ const isMissing = value === undefined;
114
+ if (hasSometimes && isMissing) {
115
+ continue;
116
+ }
117
+ const hasNullable = attributeRules.includes('nullable');
118
+ const isNullValue = value === undefined || value === null || value === '';
119
+ if (hasNullable && isNullValue) {
120
+ continue;
121
+ }
93
122
  validationPromises.push((async () => {
94
123
  let shouldBail = false;
95
124
  for (const rawRule of attributeRules) {
@@ -139,6 +168,16 @@ class Validator {
139
168
  for (const [attribute, attributeRules] of Object.entries(this.normalizedRules)) {
140
169
  const value = (0, data_1.dataGet)(this.data, attribute);
141
170
  const isEmpty = value === undefined || value === null || value === '';
171
+ const hasSometimes = attributeRules.includes('sometimes');
172
+ const isMissing = value === undefined;
173
+ if (hasSometimes && isMissing) {
174
+ continue;
175
+ }
176
+ const hasNullable = attributeRules.includes('nullable');
177
+ const isNullValue = value === undefined || value === null || value === '';
178
+ if (hasNullable && isNullValue) {
179
+ continue;
180
+ }
142
181
  let shouldBail = false;
143
182
  for (const rawRule of attributeRules) {
144
183
  if (rawRule === 'bail') {
@@ -193,6 +232,70 @@ class Validator {
193
232
  return new MinRule_js_1.MinRule(parseInt(params[0], 10));
194
233
  if (ruleName === 'max')
195
234
  return new MaxRule_js_1.MaxRule(parseInt(params[0], 10));
235
+ if (ruleName === 'string')
236
+ return new StringRule_js_1.StringRule();
237
+ if (ruleName === 'numeric')
238
+ return new NumericRule_js_1.NumericRule();
239
+ if (ruleName === 'integer')
240
+ return new IntegerRule_js_1.IntegerRule();
241
+ if (ruleName === 'boolean')
242
+ return new BooleanRule_js_1.BooleanRule();
243
+ if (ruleName === 'array')
244
+ return new ArrayRule_js_1.ArrayRule();
245
+ if (ruleName === 'nullable')
246
+ return new NullableRule_js_1.NullableRule();
247
+ if (ruleName === 'between') {
248
+ return new BetweenRule_js_1.BetweenRule(parseInt(params[0], 10), parseInt(params[1], 10));
249
+ }
250
+ if (ruleName === 'confirmed') {
251
+ return new ConfirmedRule_js_1.ConfirmedRule(this.data);
252
+ }
253
+ if (ruleName === 'same') {
254
+ return new SameRule_js_1.SameRule(params[0], this.data);
255
+ }
256
+ if (ruleName === 'date')
257
+ return new DateRule_js_1.DateRule();
258
+ if (ruleName === 'after')
259
+ return new AfterDateRule_js_1.AfterDateRule(paramString);
260
+ if (ruleName === 'before')
261
+ return new BeforeDateRule_js_1.BeforeDateRule(paramString);
262
+ if (ruleName === 'date_format')
263
+ return new DateFormatRule_js_1.DateFormatRule(paramString);
264
+ if (ruleName === 'sometimes')
265
+ return new SometimesRule_js_1.SometimesRule();
266
+ if (ruleName === 'required_if') {
267
+ const [anotherField, targetValue] = params;
268
+ return new RequiredIfRule_js_1.RequiredIfRule(anotherField, targetValue, this.data);
269
+ }
270
+ if (ruleName === 'required_unless') {
271
+ const [anotherField, targetValue] = params;
272
+ return new RequiredUnlessRule_js_1.RequiredUnlessRule(anotherField, targetValue, this.data);
273
+ }
274
+ if (ruleName === 'image')
275
+ return new ImageRule_js_1.ImageRule();
276
+ if (ruleName === 'mimes')
277
+ return new MimesRule_js_1.MimesRule(params);
278
+ if (ruleName === 'alpha')
279
+ return new AlphaRule_js_1.AlphaRule();
280
+ if (ruleName === 'alpha_num')
281
+ return new AlphaNumRule_js_1.AlphaNumRule();
282
+ if (ruleName === 'regex') {
283
+ let pattern = paramString;
284
+ let flags = '';
285
+ if (paramString.startsWith('/') &&
286
+ paramString.lastIndexOf('/') > 0) {
287
+ const lastSlash = paramString.lastIndexOf('/');
288
+ pattern = paramString.slice(1, lastSlash);
289
+ flags = paramString.slice(lastSlash + 1);
290
+ }
291
+ return new RegexRule_js_1.RegexRule(new RegExp(pattern, flags));
292
+ }
293
+ if (ruleName === 'unique' || ruleName === 'exists') {
294
+ if (!Validator.extensions[ruleName]) {
295
+ throw new Error(`The "${ruleName}" rule requires a database bridge. Please register one via Validator.extend('${ruleName}', ...) in your application bootstrapper.`);
296
+ }
297
+ return Validator.extensions[ruleName](params);
298
+ }
196
299
  if (Validator.extensions[ruleName]) {
197
300
  return Validator.extensions[ruleName](params);
198
301
  }
@@ -3,3 +3,6 @@ export interface ValidationRule {
3
3
  validate(attribute: string, value: unknown, fail: FailCallback): void;
4
4
  }
5
5
  export type CustomRuleClosureFactory = (params: string[]) => ValidationRule;
6
+ export interface ImplicitRule extends ValidationRule {
7
+ isImplicit: true;
8
+ }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,25 @@
1
1
  export * from './contracts/Validation';
2
+ export * from './rules/AfterDateRule';
3
+ export * from './rules/AlphaNumRule';
4
+ export * from './rules/AlphaRule';
5
+ export * from './rules/ArrayRule';
6
+ export * from './rules/BeforeDateRule';
7
+ export * from './rules/BooleanRule';
8
+ export * from './rules/DateFormatRule';
9
+ export * from './rules/DateRule';
2
10
  export * from './rules/EmailRule';
11
+ export * from './rules/ExistsRule';
12
+ export * from './rules/ImageRule';
13
+ export * from './rules/IntegerRule';
3
14
  export * from './rules/MaxRule';
15
+ export * from './rules/MimesRule';
4
16
  export * from './rules/MinRule';
17
+ export * from './rules/NullableRule';
18
+ export * from './rules/NumericRule';
19
+ export * from './rules/RegexRule';
5
20
  export * from './rules/RequiredRule';
21
+ export * from './rules/StringRule';
22
+ export * from './rules/UniqueRule';
6
23
  import { Validator } from './Validator';
7
24
  export * from './integrations/react';
8
25
  export * from './integrations/vue';
package/dist/index.js CHANGED
@@ -15,10 +15,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./contracts/Validation"), exports);
18
+ __exportStar(require("./rules/AfterDateRule"), exports);
19
+ __exportStar(require("./rules/AlphaNumRule"), exports);
20
+ __exportStar(require("./rules/AlphaRule"), exports);
21
+ __exportStar(require("./rules/ArrayRule"), exports);
22
+ __exportStar(require("./rules/BeforeDateRule"), exports);
23
+ __exportStar(require("./rules/BooleanRule"), exports);
24
+ __exportStar(require("./rules/DateFormatRule"), exports);
25
+ __exportStar(require("./rules/DateRule"), exports);
18
26
  __exportStar(require("./rules/EmailRule"), exports);
27
+ __exportStar(require("./rules/ExistsRule"), exports);
28
+ __exportStar(require("./rules/ImageRule"), exports);
29
+ __exportStar(require("./rules/IntegerRule"), exports);
19
30
  __exportStar(require("./rules/MaxRule"), exports);
31
+ __exportStar(require("./rules/MimesRule"), exports);
20
32
  __exportStar(require("./rules/MinRule"), exports);
33
+ __exportStar(require("./rules/NullableRule"), exports);
34
+ __exportStar(require("./rules/NumericRule"), exports);
35
+ __exportStar(require("./rules/RegexRule"), exports);
21
36
  __exportStar(require("./rules/RequiredRule"), exports);
37
+ __exportStar(require("./rules/StringRule"), exports);
38
+ __exportStar(require("./rules/UniqueRule"), exports);
22
39
  const Validator_1 = require("./Validator");
23
40
  __exportStar(require("./integrations/react"), exports);
24
41
  __exportStar(require("./integrations/vue"), exports);
@@ -0,0 +1,6 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class AfterDateRule implements ValidationRule {
3
+ private targetDateString;
4
+ constructor(targetDateString: string);
5
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AfterDateRule = void 0;
4
+ class AfterDateRule {
5
+ targetDateString;
6
+ constructor(targetDateString) {
7
+ this.targetDateString = targetDateString;
8
+ }
9
+ validate(attribute, value, fail) {
10
+ const valueTime = Date.parse(String(value));
11
+ const targetTime = Date.parse(this.targetDateString);
12
+ if (isNaN(targetTime)) {
13
+ throw new Error(`The validation boundary date "${this.targetDateString}" is invalid.`);
14
+ }
15
+ if (isNaN(valueTime) || valueTime <= targetTime) {
16
+ fail(`The :attribute must be a date after ${this.targetDateString}.`);
17
+ }
18
+ }
19
+ }
20
+ exports.AfterDateRule = AfterDateRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class AlphaNumRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AlphaNumRule = void 0;
4
+ class AlphaNumRule {
5
+ validate(attribute, value, fail) {
6
+ const stringValue = String(value);
7
+ if (!/^[A-Za-z0-9]+$/.test(stringValue)) {
8
+ fail(`The :attribute must only contain letters and numbers.`);
9
+ }
10
+ }
11
+ }
12
+ exports.AlphaNumRule = AlphaNumRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class AlphaRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AlphaRule = void 0;
4
+ class AlphaRule {
5
+ validate(attribute, value, fail) {
6
+ if (typeof value !== 'string' || !/^[A-Za-z]+$/.test(value)) {
7
+ fail(`The :attribute must only contain letters.`);
8
+ }
9
+ }
10
+ }
11
+ exports.AlphaRule = AlphaRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class ArrayRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ArrayRule = void 0;
4
+ class ArrayRule {
5
+ validate(attribute, value, fail) {
6
+ if (!Array.isArray(value)) {
7
+ fail(`The :attribute must be an array.`);
8
+ }
9
+ }
10
+ }
11
+ exports.ArrayRule = ArrayRule;
@@ -0,0 +1,6 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class BeforeDateRule implements ValidationRule {
3
+ private targetDateString;
4
+ constructor(targetDateString: string);
5
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BeforeDateRule = void 0;
4
+ class BeforeDateRule {
5
+ targetDateString;
6
+ constructor(targetDateString) {
7
+ this.targetDateString = targetDateString;
8
+ }
9
+ validate(attribute, value, fail) {
10
+ const valueTime = Date.parse(String(value));
11
+ const targetTime = Date.parse(this.targetDateString);
12
+ if (isNaN(targetTime)) {
13
+ throw new Error(`The validation boundary date "${this.targetDateString}" is invalid.`);
14
+ }
15
+ if (isNaN(valueTime) || valueTime >= targetTime) {
16
+ fail(`The :attribute must be a date before ${this.targetDateString}.`);
17
+ }
18
+ }
19
+ }
20
+ exports.BeforeDateRule = BeforeDateRule;
@@ -0,0 +1,7 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class BetweenRule implements ValidationRule {
3
+ private min;
4
+ private max;
5
+ constructor(min: number, max: number);
6
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
7
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BetweenRule = void 0;
4
+ class BetweenRule {
5
+ min;
6
+ max;
7
+ constructor(min, max) {
8
+ this.min = min;
9
+ this.max = max;
10
+ }
11
+ validate(attribute, value, fail) {
12
+ let size;
13
+ if (Array.isArray(value)) {
14
+ size = value.length;
15
+ }
16
+ else if (typeof value === 'number') {
17
+ size = value;
18
+ }
19
+ else if (typeof value === 'string') {
20
+ // If it looks numeric, treat it as a number; otherwise, check character length
21
+ size =
22
+ !isNaN(Number(value)) && value.trim() !== ''
23
+ ? Number(value)
24
+ : [...value].length;
25
+ }
26
+ else {
27
+ return; // Skip unsupported types gracefully
28
+ }
29
+ if (size < this.min || size > this.max) {
30
+ fail(`The :attribute must be between ${this.min} and ${this.max}.`);
31
+ }
32
+ }
33
+ }
34
+ exports.BetweenRule = BetweenRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class BooleanRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BooleanRule = void 0;
4
+ class BooleanRule {
5
+ validate(attribute, value, fail) {
6
+ const acceptable = [true, false, 1, 0, '1', '0', 'true', 'false'];
7
+ if (!acceptable.includes(value)) {
8
+ fail(`The :attribute field must be true or false.`);
9
+ }
10
+ }
11
+ }
12
+ exports.BooleanRule = BooleanRule;
@@ -0,0 +1,6 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class ConfirmedRule implements ValidationRule {
3
+ private allData;
4
+ constructor(allData: Record<string, unknown>);
5
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmedRule = void 0;
4
+ class ConfirmedRule {
5
+ allData;
6
+ // We accept the full root data object via the constructor
7
+ constructor(allData) {
8
+ this.allData = allData;
9
+ }
10
+ validate(attribute, value, fail) {
11
+ const confirmationField = `${attribute}_confirmation`;
12
+ const confirmationValue = this.allData[confirmationField];
13
+ if (value !== confirmationValue) {
14
+ fail(`The :attribute confirmation does not match.`);
15
+ }
16
+ }
17
+ }
18
+ exports.ConfirmedRule = ConfirmedRule;
@@ -0,0 +1,6 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class DateFormatRule implements ValidationRule {
3
+ private format;
4
+ constructor(format: string);
5
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
6
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DateFormatRule = void 0;
4
+ class DateFormatRule {
5
+ format;
6
+ constructor(format) {
7
+ this.format = format;
8
+ }
9
+ validate(attribute, value, fail) {
10
+ if (typeof value !== 'string') {
11
+ fail(`The :attribute does not match the format ${this.format}.`);
12
+ return;
13
+ }
14
+ // 🚀 Clean token isolation using exact character boundary maps
15
+ let regexString = this.format
16
+ .replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') // 1. Escape layout boundaries first
17
+ .replace(/d/g, '(0[1-9]|[12]\\d|3[01])') // 2. Replace 'd' BEFORE injecting matching '\\d' tokens
18
+ .replace(/Y/g, '\\d{4}') // 3. Replace 'Y' (4-digit Year)
19
+ .replace(/m/g, '(0[1-9]|1[0-2])') // 4. Replace 'm' (2-digit Month)
20
+ .replace(/H/g, '(0\\d|1\\d|2[0-3])') // 5. Replace 'H' (24-Hour)
21
+ .replace(/i/g, '[0-5]\\d') // 6. Replace 'i' (Minutes)
22
+ .replace(/s/g, '[0-5]\\d'); // 7. Replace 's' (Seconds)
23
+ const strictRegex = new RegExp(`^${regexString}$`);
24
+ if (!strictRegex.test(value)) {
25
+ fail(`The :attribute does not match the format ${this.format}.`);
26
+ }
27
+ }
28
+ }
29
+ exports.DateFormatRule = DateFormatRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class DateRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DateRule = void 0;
4
+ class DateRule {
5
+ validate(attribute, value, fail) {
6
+ if (value instanceof Date && !isNaN(value.getTime())) {
7
+ return;
8
+ }
9
+ if (typeof value !== 'string' && typeof value !== 'number') {
10
+ fail(`The :attribute is not a valid date.`);
11
+ return;
12
+ }
13
+ const timestamp = Date.parse(String(value));
14
+ if (isNaN(timestamp)) {
15
+ fail(`The :attribute is not a valid date.`);
16
+ }
17
+ }
18
+ }
19
+ exports.DateRule = DateRule;
@@ -0,0 +1,8 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare abstract class ExistsRule implements ValidationRule {
3
+ protected table: string;
4
+ protected column: string;
5
+ constructor(table: string, column: string);
6
+ abstract existsInDatabase(table: string, column: string, value: unknown): Promise<boolean>;
7
+ validate(attribute: string, value: unknown, fail: FailCallback): Promise<void>;
8
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExistsRule = void 0;
4
+ class ExistsRule {
5
+ table;
6
+ column;
7
+ constructor(table, column) {
8
+ this.table = table;
9
+ this.column = column;
10
+ }
11
+ async validate(attribute, value, fail) {
12
+ if (value === undefined || value === null || value === '')
13
+ return;
14
+ const exists = await this.existsInDatabase(this.table, this.column, value);
15
+ if (!exists) {
16
+ fail(`The selected :attribute is invalid.`);
17
+ }
18
+ }
19
+ }
20
+ exports.ExistsRule = ExistsRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class ImageRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImageRule = void 0;
4
+ class ImageRule {
5
+ validate(attribute, value, fail) {
6
+ const allowedExtensions = [
7
+ 'jpeg',
8
+ 'jpg',
9
+ 'png',
10
+ 'bmp',
11
+ 'gif',
12
+ 'svg',
13
+ 'webp',
14
+ ];
15
+ let filename = '';
16
+ if (typeof value === 'string') {
17
+ filename = value;
18
+ }
19
+ else if (value && typeof value === 'object' && 'name' in value) {
20
+ filename = String(value.name);
21
+ }
22
+ else {
23
+ fail(`The :attribute must be an image.`);
24
+ return;
25
+ }
26
+ const extension = filename.split('.').pop()?.toLowerCase() || '';
27
+ if (!allowedExtensions.includes(extension)) {
28
+ fail(`The :attribute must be an image.`);
29
+ }
30
+ }
31
+ }
32
+ exports.ImageRule = ImageRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class IntegerRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IntegerRule = void 0;
4
+ class IntegerRule {
5
+ validate(attribute, value, fail) {
6
+ const num = Number(value);
7
+ const isInteger = !isNaN(num) && Number.isInteger(num) && String(value).trim() !== '';
8
+ if (!isInteger) {
9
+ fail(`The :attribute must be an integer.`);
10
+ }
11
+ }
12
+ }
13
+ exports.IntegerRule = IntegerRule;
@@ -0,0 +1,6 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class MimesRule implements ValidationRule {
3
+ private allowedExtensions;
4
+ constructor(allowedExtensions: string[]);
5
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
6
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MimesRule = void 0;
4
+ class MimesRule {
5
+ allowedExtensions;
6
+ constructor(allowedExtensions) {
7
+ this.allowedExtensions = allowedExtensions;
8
+ }
9
+ validate(attribute, value, fail) {
10
+ let filename = '';
11
+ if (typeof value === 'string') {
12
+ filename = value;
13
+ }
14
+ else if (value && typeof value === 'object' && 'name' in value) {
15
+ filename = String(value.name);
16
+ }
17
+ else {
18
+ fail(`The :attribute must be a file of type: ${this.allowedExtensions.join(', ')}.`);
19
+ return;
20
+ }
21
+ const extension = filename.split('.').pop()?.toLowerCase() || '';
22
+ if (!this.allowedExtensions
23
+ .map((ext) => ext.toLowerCase())
24
+ .includes(extension)) {
25
+ fail(`The :attribute must be a file of type: ${this.allowedExtensions.join(', ')}.`);
26
+ }
27
+ }
28
+ }
29
+ exports.MimesRule = MimesRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class NullableRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NullableRule = void 0;
4
+ class NullableRule {
5
+ validate(attribute, value, fail) { }
6
+ }
7
+ exports.NullableRule = NullableRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class NumericRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NumericRule = void 0;
4
+ class NumericRule {
5
+ validate(attribute, value, fail) {
6
+ // Allows pure numbers or numeric strings (like "123" or "45.6")
7
+ const isNumeric = (typeof value === 'number' && !isNaN(value)) ||
8
+ (typeof value === 'string' &&
9
+ value.trim() !== '' &&
10
+ !isNaN(Number(value)));
11
+ if (!isNumeric) {
12
+ fail(`The :attribute must be a number.`);
13
+ }
14
+ }
15
+ }
16
+ exports.NumericRule = NumericRule;
@@ -0,0 +1,6 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class RegexRule implements ValidationRule {
3
+ private pattern;
4
+ constructor(pattern: RegExp);
5
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
6
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegexRule = void 0;
4
+ class RegexRule {
5
+ pattern;
6
+ constructor(pattern) {
7
+ this.pattern = pattern;
8
+ }
9
+ validate(attribute, value, fail) {
10
+ const stringValue = String(value);
11
+ if (!this.pattern.test(stringValue)) {
12
+ fail(`The :attribute format is invalid.`);
13
+ }
14
+ }
15
+ }
16
+ exports.RegexRule = RegexRule;
@@ -0,0 +1,9 @@
1
+ import { FailCallback, ImplicitRule } from '../contracts/Validation';
2
+ export declare class RequiredIfRule implements ImplicitRule {
3
+ private anotherField;
4
+ private targetValue;
5
+ private allData;
6
+ isImplicit: true;
7
+ constructor(anotherField: string, targetValue: string, allData: Record<string, unknown>);
8
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
9
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RequiredIfRule = void 0;
4
+ const data_1 = require("../utils/data");
5
+ class RequiredIfRule {
6
+ anotherField;
7
+ targetValue;
8
+ allData;
9
+ isImplicit = true; // Must be implicit to run when the field is missing
10
+ constructor(anotherField, targetValue, allData) {
11
+ this.anotherField = anotherField;
12
+ this.targetValue = targetValue;
13
+ this.allData = allData;
14
+ }
15
+ validate(attribute, value, fail) {
16
+ const actualValue = (0, data_1.dataGet)(this.allData, this.anotherField);
17
+ // Cast comparison value to string to ensure fluid loose matching (handles numbers/booleans)
18
+ if (String(actualValue) === this.targetValue) {
19
+ if (value === undefined || value === null || value === '') {
20
+ fail(`The :attribute field is required when ${this.anotherField} is ${this.targetValue}.`);
21
+ }
22
+ }
23
+ }
24
+ }
25
+ exports.RequiredIfRule = RequiredIfRule;
@@ -0,0 +1,9 @@
1
+ import { FailCallback, ImplicitRule } from '../contracts/Validation';
2
+ export declare class RequiredUnlessRule implements ImplicitRule {
3
+ private anotherField;
4
+ private targetValue;
5
+ private allData;
6
+ isImplicit: true;
7
+ constructor(anotherField: string, targetValue: string, allData: Record<string, unknown>);
8
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RequiredUnlessRule = void 0;
4
+ const data_1 = require("../utils/data");
5
+ class RequiredUnlessRule {
6
+ anotherField;
7
+ targetValue;
8
+ allData;
9
+ isImplicit = true;
10
+ constructor(anotherField, targetValue, allData) {
11
+ this.anotherField = anotherField;
12
+ this.targetValue = targetValue;
13
+ this.allData = allData;
14
+ }
15
+ validate(attribute, value, fail) {
16
+ const actualValue = (0, data_1.dataGet)(this.allData, this.anotherField);
17
+ if (String(actualValue) !== this.targetValue) {
18
+ if (value === undefined || value === null || value === '') {
19
+ fail(`The :attribute field is required unless ${this.anotherField} is ${this.targetValue}.`);
20
+ }
21
+ }
22
+ }
23
+ }
24
+ exports.RequiredUnlessRule = RequiredUnlessRule;
@@ -0,0 +1,7 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class SameRule implements ValidationRule {
3
+ private otherField;
4
+ private allData;
5
+ constructor(otherField: string, allData: Record<string, unknown>);
6
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
7
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SameRule = void 0;
4
+ const data_1 = require("../utils/data");
5
+ class SameRule {
6
+ otherField;
7
+ allData;
8
+ constructor(otherField, allData) {
9
+ this.otherField = otherField;
10
+ this.allData = allData;
11
+ }
12
+ validate(attribute, value, fail) {
13
+ // Uses our dot-notation utility helper to grab the comparison value safely
14
+ const otherValue = (0, data_1.dataGet)(this.allData, this.otherField);
15
+ if (value !== otherValue) {
16
+ fail(`The :attribute and ${this.otherField} must match.`);
17
+ }
18
+ }
19
+ }
20
+ exports.SameRule = SameRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class SometimesRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SometimesRule = void 0;
4
+ class SometimesRule {
5
+ validate(attribute, value, fail) { }
6
+ }
7
+ exports.SometimesRule = SometimesRule;
@@ -0,0 +1,4 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare class StringRule implements ValidationRule {
3
+ validate(attribute: string, value: unknown, fail: FailCallback): void;
4
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StringRule = void 0;
4
+ class StringRule {
5
+ validate(attribute, value, fail) {
6
+ if (typeof value !== 'string') {
7
+ fail(`The :attribute must be a string.`);
8
+ }
9
+ }
10
+ }
11
+ exports.StringRule = StringRule;
@@ -0,0 +1,8 @@
1
+ import { FailCallback, ValidationRule } from '../contracts/Validation';
2
+ export declare abstract class UniqueRule implements ValidationRule {
3
+ protected table: string;
4
+ protected column: string;
5
+ constructor(table: string, column: string);
6
+ abstract isUnique(table: string, column: string, value: unknown): Promise<boolean>;
7
+ validate(attribute: string, value: unknown, fail: FailCallback): Promise<void>;
8
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniqueRule = void 0;
4
+ class UniqueRule {
5
+ table;
6
+ column;
7
+ constructor(table, column) {
8
+ this.table = table;
9
+ this.column = column;
10
+ }
11
+ async validate(attribute, value, fail) {
12
+ if (value === undefined || value === null || value === '')
13
+ return;
14
+ const unique = await this.isUnique(this.table, this.column, value);
15
+ if (!unique) {
16
+ fail(`The :attribute has already been taken.`);
17
+ }
18
+ }
19
+ }
20
+ exports.UniqueRule = UniqueRule;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbl-dev/validator-ts",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "A Laravel-inspired class-based pipe validator for TypeScript applications.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",