kanun 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs +15 -6
- package/dist/index.d.ts +100 -89
- package/dist/index.js +15 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ npm install kanun
|
|
|
16
16
|
For file validation, install the separate plugin package:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm install kanun kanun-plugin-file
|
|
19
|
+
npm install kanun @kanun-hq/plugin-file
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## Features
|
|
@@ -157,7 +157,7 @@ const validator = new Validator(
|
|
|
157
157
|
|
|
158
158
|
### Plugins
|
|
159
159
|
|
|
160
|
-
Kanun supports installable plugins such as
|
|
160
|
+
Kanun supports installable plugins such as `@kanun-hq/plugin-file`.
|
|
161
161
|
|
|
162
162
|
Plugin usage, file validation rules, and framework upload adapters are fully documented:
|
|
163
163
|
|
package/dist/index.cjs
CHANGED
|
@@ -2355,7 +2355,7 @@ var BaseValidator = class BaseValidator {
|
|
|
2355
2355
|
[rule, parameters] = validationRuleParser.parse(rule);
|
|
2356
2356
|
const keys = this.getExplicitKeys(attribute);
|
|
2357
2357
|
if (keys.length > 0 && parameters.length > 0) parameters = this.replaceAsterisksInParameters(parameters, keys);
|
|
2358
|
-
const value =
|
|
2358
|
+
const value = this.getAttributeValue(attribute);
|
|
2359
2359
|
const validatable = this.isValidatable(attribute, value, rule);
|
|
2360
2360
|
if (rule instanceof IRuleContract) return validatable ? this.validateUsingCustomRule(attribute, value, rule) : void 0;
|
|
2361
2361
|
const method = `validate${buildValidationMethodName(rule)}`;
|
|
@@ -2423,14 +2423,14 @@ var BaseValidator = class BaseValidator {
|
|
|
2423
2423
|
* Determine if the attribute is validatable.
|
|
2424
2424
|
*/
|
|
2425
2425
|
isValidatable(attribute, value, rule) {
|
|
2426
|
-
return this.presentOrRuleIsImplicit(attribute, value, rule) && this.passesOptionalCheck(attribute) && this.isNotNullIfMarkedAsNullable(attribute, rule);
|
|
2426
|
+
return this.presentOrRuleIsImplicit(attribute, value, rule) && this.passesOptionalCheck(attribute) && this.isNotNullIfMarkedAsNullable(attribute, value, rule);
|
|
2427
2427
|
}
|
|
2428
2428
|
/**
|
|
2429
2429
|
* Determine if the field is present, or the rule implies required.
|
|
2430
2430
|
*/
|
|
2431
2431
|
presentOrRuleIsImplicit(attribute, value, rule) {
|
|
2432
2432
|
if (typeof value === "string" && value.trim() === "") return isImplicitRule(rule);
|
|
2433
|
-
return typeof
|
|
2433
|
+
return typeof value !== "undefined" || isImplicitRule(rule);
|
|
2434
2434
|
}
|
|
2435
2435
|
/**
|
|
2436
2436
|
* Determine if the attribute passes any optional check.
|
|
@@ -2438,14 +2438,23 @@ var BaseValidator = class BaseValidator {
|
|
|
2438
2438
|
passesOptionalCheck(attribute) {
|
|
2439
2439
|
if (!validationRuleParser.hasRule(attribute, ["sometimes"], this.rules)) return true;
|
|
2440
2440
|
const data = validationData.initializeAndGatherData(attribute, this.data);
|
|
2441
|
-
|
|
2441
|
+
const requestFiles = validationData.initializeAndGatherData(attribute, this.getContext().requestFiles ?? {});
|
|
2442
|
+
return Object.prototype.hasOwnProperty.call(data, attribute) || Object.prototype.hasOwnProperty.call(this.data, attribute) || Object.prototype.hasOwnProperty.call(requestFiles, attribute) || Object.prototype.hasOwnProperty.call(this.getContext().requestFiles ?? {}, attribute);
|
|
2442
2443
|
}
|
|
2443
2444
|
/**
|
|
2444
2445
|
* Determine if the attribute fails the nullable check.
|
|
2445
2446
|
*/
|
|
2446
|
-
isNotNullIfMarkedAsNullable(attribute, rule) {
|
|
2447
|
+
isNotNullIfMarkedAsNullable(attribute, value, rule) {
|
|
2447
2448
|
if (isImplicitRule(rule) || !validationRuleParser.hasRule(attribute, ["nullable"], this.rules)) return true;
|
|
2448
|
-
return
|
|
2449
|
+
return value !== null;
|
|
2450
|
+
}
|
|
2451
|
+
/**
|
|
2452
|
+
* Resolve an attribute value from validator data first, then request-scoped file context.
|
|
2453
|
+
*/
|
|
2454
|
+
getAttributeValue(attribute) {
|
|
2455
|
+
const dataValue = deepFind(this.data, attribute);
|
|
2456
|
+
if (typeof dataValue !== "undefined") return dataValue;
|
|
2457
|
+
return deepFind(this.getContext().requestFiles ?? {}, attribute);
|
|
2449
2458
|
}
|
|
2450
2459
|
/**
|
|
2451
2460
|
* Get the primary attribute name
|
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,100 @@ declare abstract class IRuleContract {
|
|
|
45
45
|
trans(path: string, params?: GenericObject): string;
|
|
46
46
|
}
|
|
47
47
|
//#endregion
|
|
48
|
+
//#region src/Rules/in.d.ts
|
|
49
|
+
declare class In extends BaseRule {
|
|
50
|
+
/**
|
|
51
|
+
* The name of the rule.
|
|
52
|
+
*/
|
|
53
|
+
rule: string;
|
|
54
|
+
/**
|
|
55
|
+
* The accepted values.
|
|
56
|
+
*/
|
|
57
|
+
values: (string | number)[];
|
|
58
|
+
/**
|
|
59
|
+
* Create a new In rule instance.
|
|
60
|
+
*/
|
|
61
|
+
constructor(values: (string | number)[]);
|
|
62
|
+
/**
|
|
63
|
+
* Convert the rule to a validation string.
|
|
64
|
+
*/
|
|
65
|
+
toString(): string;
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/Rules/notIn.d.ts
|
|
69
|
+
declare class NotIn extends BaseRule {
|
|
70
|
+
/**
|
|
71
|
+
* The name of the rule.
|
|
72
|
+
*/
|
|
73
|
+
rule: string;
|
|
74
|
+
/**
|
|
75
|
+
* The accepted values.
|
|
76
|
+
*/
|
|
77
|
+
values: (string | number)[];
|
|
78
|
+
/**
|
|
79
|
+
* Create a new NotIn rule instance.
|
|
80
|
+
*/
|
|
81
|
+
constructor(values: (string | number)[]);
|
|
82
|
+
/**
|
|
83
|
+
* Convert the rule to a validation string.
|
|
84
|
+
*/
|
|
85
|
+
toString(): string;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/Rules/regex.d.ts
|
|
89
|
+
declare class Regex extends IRuleContract {
|
|
90
|
+
/**
|
|
91
|
+
* The Regular expression to validate
|
|
92
|
+
*/
|
|
93
|
+
regex: RegExp;
|
|
94
|
+
/**
|
|
95
|
+
* Flag that decides whether the value should match the regular expression or not
|
|
96
|
+
*/
|
|
97
|
+
shouldMatch: boolean;
|
|
98
|
+
constructor(regex: RegExp, shouldMatch?: boolean);
|
|
99
|
+
passes(value: any): boolean;
|
|
100
|
+
getMessage(): string;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/Rules/requiredIf.d.ts
|
|
104
|
+
declare class RequiredIf extends BaseRule {
|
|
105
|
+
/**
|
|
106
|
+
* The condition that validates the attribute
|
|
107
|
+
*/
|
|
108
|
+
condition: boolean | CallableFunction;
|
|
109
|
+
/**
|
|
110
|
+
* Create a new required validation rule based on a condition.
|
|
111
|
+
*/
|
|
112
|
+
constructor(condition: boolean | CallableFunction);
|
|
113
|
+
/**
|
|
114
|
+
* Convert the rule to a validation string.
|
|
115
|
+
*/
|
|
116
|
+
toString(): string;
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region src/Contracts/ValidationRuleName.d.ts
|
|
120
|
+
type ValidationRuleAutocompleteKind = 'plain' | 'paramable';
|
|
121
|
+
interface ValidationRuleAutocompleteMap {}
|
|
122
|
+
/**
|
|
123
|
+
* Backward-compatible alias for older plugin augmentations.
|
|
124
|
+
*/
|
|
125
|
+
interface CustomValidationRuleNameMap {}
|
|
126
|
+
type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>);
|
|
127
|
+
type PluginValidationRuleNameMap = ValidationRuleAutocompleteMap & CustomValidationRuleNameMap;
|
|
128
|
+
type CustomParamableValidationRuleName = Extract<{ [K in keyof PluginValidationRuleNameMap]: PluginValidationRuleNameMap[K] extends 'paramable' ? K : never }[keyof PluginValidationRuleNameMap], string>;
|
|
129
|
+
type CustomPlainRuleName = Extract<{ [K in keyof PluginValidationRuleNameMap]: PluginValidationRuleNameMap[K] extends 'plain' ? K : never }[keyof PluginValidationRuleNameMap], string>;
|
|
130
|
+
type ParamableValidationRuleName = 'accepted_if' | 'after' | 'after_or_equal' | 'before' | 'before_or_equal' | 'between' | 'date_equals' | 'datetime' | 'declined_if' | 'digits_between' | 'different' | 'exists' | 'ends_with' | 'gt' | 'gte' | 'in' | 'includes' | 'lt' | 'lte' | 'max' | 'min' | 'not_in' | 'not_includes' | 'required_if' | 'required_unless' | 'required_with' | 'required_with_all' | 'required_without' | 'required_without_all' | 'same' | 'size' | 'starts_with' | 'unique' | CustomParamableValidationRuleName;
|
|
131
|
+
type PlainRuleName = 'accepted' | 'alpha' | 'alpha_dash' | 'alpha_num' | 'array' | 'array_unique' | 'bail' | 'boolean' | 'confirmed' | 'date' | 'declined' | 'digits' | 'email' | 'integer' | 'json' | 'not_regex' | 'nullable' | 'numeric' | 'object' | 'present' | 'regex' | 'required' | 'sometimes' | 'string' | 'url' | 'hex' | 'uuid' | CustomPlainRuleName;
|
|
132
|
+
type ValidationRuleName = ParamableValidationRuleName | PlainRuleName;
|
|
133
|
+
type MethodRules = Regex | In | NotIn | RequiredIf;
|
|
134
|
+
type ParamableRuleString = `${ParamableValidationRuleName}:${string}`;
|
|
135
|
+
type ValidationRuleString = LiteralUnion<ValidationRuleName | ParamableRuleString>;
|
|
136
|
+
/**
|
|
137
|
+
* Single rule value (supports autocomplete + arbitrary strings + RuleContract instances)
|
|
138
|
+
*/
|
|
139
|
+
type ValidationRuleEntry = ValidationRuleString | IRuleContract | MethodRules;
|
|
140
|
+
type ValidationRuleSet = ValidationRuleEntry | readonly ValidationRuleEntry[] | LiteralUnion<`${ValidationRuleName}${string & `|${string}`}` | `${ParamableRuleString}${string & `|${string}`}`>;
|
|
141
|
+
//#endregion
|
|
48
142
|
//#region src/payloads/replaceAttributePayload.d.ts
|
|
49
143
|
declare class replaceAttributePayload {
|
|
50
144
|
/**
|
|
@@ -71,7 +165,7 @@ declare class replaceAttributePayload {
|
|
|
71
165
|
}
|
|
72
166
|
//#endregion
|
|
73
167
|
//#region src/Contracts/BaseContract.d.ts
|
|
74
|
-
type InitialRule =
|
|
168
|
+
type InitialRule = ValidationRuleEntry | ValidationCallback | BaseRule;
|
|
75
169
|
type TRule = string | IRuleContract;
|
|
76
170
|
type NestedStringMap = {
|
|
77
171
|
[key: string]: string | NestedStringMap;
|
|
@@ -509,6 +603,10 @@ declare class BaseValidator<D extends GenericObject = GenericObject> {
|
|
|
509
603
|
* Determine if the attribute fails the nullable check.
|
|
510
604
|
*/
|
|
511
605
|
private isNotNullIfMarkedAsNullable;
|
|
606
|
+
/**
|
|
607
|
+
* Resolve an attribute value from validator data first, then request-scoped file context.
|
|
608
|
+
*/
|
|
609
|
+
private getAttributeValue;
|
|
512
610
|
/**
|
|
513
611
|
* Get the primary attribute name
|
|
514
612
|
*
|
|
@@ -664,93 +762,6 @@ declare abstract class IValidationRule {
|
|
|
664
762
|
passes(value: any, attribute: string): boolean | Promise<boolean>;
|
|
665
763
|
}
|
|
666
764
|
//#endregion
|
|
667
|
-
//#region src/Rules/in.d.ts
|
|
668
|
-
declare class In extends BaseRule {
|
|
669
|
-
/**
|
|
670
|
-
* The name of the rule.
|
|
671
|
-
*/
|
|
672
|
-
rule: string;
|
|
673
|
-
/**
|
|
674
|
-
* The accepted values.
|
|
675
|
-
*/
|
|
676
|
-
values: (string | number)[];
|
|
677
|
-
/**
|
|
678
|
-
* Create a new In rule instance.
|
|
679
|
-
*/
|
|
680
|
-
constructor(values: (string | number)[]);
|
|
681
|
-
/**
|
|
682
|
-
* Convert the rule to a validation string.
|
|
683
|
-
*/
|
|
684
|
-
toString(): string;
|
|
685
|
-
}
|
|
686
|
-
//#endregion
|
|
687
|
-
//#region src/Rules/notIn.d.ts
|
|
688
|
-
declare class NotIn extends BaseRule {
|
|
689
|
-
/**
|
|
690
|
-
* The name of the rule.
|
|
691
|
-
*/
|
|
692
|
-
rule: string;
|
|
693
|
-
/**
|
|
694
|
-
* The accepted values.
|
|
695
|
-
*/
|
|
696
|
-
values: (string | number)[];
|
|
697
|
-
/**
|
|
698
|
-
* Create a new NotIn rule instance.
|
|
699
|
-
*/
|
|
700
|
-
constructor(values: (string | number)[]);
|
|
701
|
-
/**
|
|
702
|
-
* Convert the rule to a validation string.
|
|
703
|
-
*/
|
|
704
|
-
toString(): string;
|
|
705
|
-
}
|
|
706
|
-
//#endregion
|
|
707
|
-
//#region src/Rules/regex.d.ts
|
|
708
|
-
declare class Regex extends IRuleContract {
|
|
709
|
-
/**
|
|
710
|
-
* The Regular expression to validate
|
|
711
|
-
*/
|
|
712
|
-
regex: RegExp;
|
|
713
|
-
/**
|
|
714
|
-
* Flag that decides whether the value should match the regular expression or not
|
|
715
|
-
*/
|
|
716
|
-
shouldMatch: boolean;
|
|
717
|
-
constructor(regex: RegExp, shouldMatch?: boolean);
|
|
718
|
-
passes(value: any): boolean;
|
|
719
|
-
getMessage(): string;
|
|
720
|
-
}
|
|
721
|
-
//#endregion
|
|
722
|
-
//#region src/Rules/requiredIf.d.ts
|
|
723
|
-
declare class RequiredIf extends BaseRule {
|
|
724
|
-
/**
|
|
725
|
-
* The condition that validates the attribute
|
|
726
|
-
*/
|
|
727
|
-
condition: boolean | CallableFunction;
|
|
728
|
-
/**
|
|
729
|
-
* Create a new required validation rule based on a condition.
|
|
730
|
-
*/
|
|
731
|
-
constructor(condition: boolean | CallableFunction);
|
|
732
|
-
/**
|
|
733
|
-
* Convert the rule to a validation string.
|
|
734
|
-
*/
|
|
735
|
-
toString(): string;
|
|
736
|
-
}
|
|
737
|
-
//#endregion
|
|
738
|
-
//#region src/Contracts/ValidationRuleName.d.ts
|
|
739
|
-
interface CustomValidationRuleNameMap {
|
|
740
|
-
[key: string]: any;
|
|
741
|
-
}
|
|
742
|
-
type CustomParamableValidationRuleName = Extract<{ [K in keyof CustomValidationRuleNameMap]: CustomValidationRuleNameMap[K] extends 'paramable' ? K : never }[keyof CustomValidationRuleNameMap], string>;
|
|
743
|
-
type CustomPlainRuleName = Extract<{ [K in keyof CustomValidationRuleNameMap]: CustomValidationRuleNameMap[K] extends 'plain' ? K : never }[keyof CustomValidationRuleNameMap], string>;
|
|
744
|
-
type ParamableValidationRuleName = 'accepted_if' | 'after' | 'after_or_equal' | 'before' | 'before_or_equal' | 'between' | 'date_equals' | 'datetime' | 'declined_if' | 'digits_between' | 'different' | 'exists' | 'ends_with' | 'gt' | 'gte' | 'in' | 'includes' | 'lt' | 'lte' | 'max' | 'min' | 'not_in' | 'not_includes' | 'required_if' | 'required_unless' | 'required_with' | 'required_with_all' | 'required_without' | 'required_without_all' | 'same' | 'size' | 'starts_with' | 'unique' | CustomParamableValidationRuleName;
|
|
745
|
-
type PlainRuleName = 'accepted' | 'alpha' | 'alpha_dash' | 'alpha_num' | 'array' | 'array_unique' | 'bail' | 'boolean' | 'confirmed' | 'date' | 'declined' | 'digits' | 'email' | 'integer' | 'json' | 'not_regex' | 'nullable' | 'numeric' | 'object' | 'present' | 'regex' | 'required' | 'sometimes' | 'string' | 'url' | 'hex' | 'uuid' | CustomPlainRuleName;
|
|
746
|
-
type ValidationRuleName = ParamableValidationRuleName | PlainRuleName;
|
|
747
|
-
type MethodRules = Regex | In | NotIn | RequiredIf;
|
|
748
|
-
/**
|
|
749
|
-
* Single rule value (supports autocomplete + arbitrary strings + RuleContract instances)
|
|
750
|
-
*/
|
|
751
|
-
type RuleName = ValidationRuleName | `${ParamableValidationRuleName}:${string}` | IRuleContract | MethodRules;
|
|
752
|
-
type ValidationRuleSet = RuleName | RuleName[] | `${ValidationRuleName}${string & `|${string}`}`;
|
|
753
|
-
//#endregion
|
|
754
765
|
//#region src/Contracts/ValidatorContracts.d.ts
|
|
755
766
|
/**
|
|
756
767
|
* Parse rule names from rule string or string[] definitions
|
|
@@ -1613,4 +1624,4 @@ declare class ValidationException extends Error {
|
|
|
1613
1624
|
getResponse(): any;
|
|
1614
1625
|
}
|
|
1615
1626
|
//#endregion
|
|
1616
|
-
export { BaseValidationRuleClass, BaseValidator, CustomAttributes, CustomErrors, CustomMessages, CustomParamableValidationRuleName, CustomPlainRuleName, CustomValidationRuleNameMap, CustomValidationRules, DotPaths, ErrorBag, ErrorMessage, Errors, ExtendedRules, ExtractRules, FieldMessages, GenericCallable, GenericObject, IDatabaseDriver, IMessageBag, IValidationRule, IValidator, ImplicitAttributes, ImplicitRule, InitialRule, InitialRules, Lang, MessageBag, Messages, MessagesForRules, NestedStringMap, ParamableValidationRuleName, Password, PlainRuleName, ReplaceAttributeInterface, Rules, RulesForData, TRule, ValidatedByRules, ValidationCallback, ValidationDataInterface, ValidationDatabaseExistsInput, ValidationException, ValidationMessageProvider, ValidationRule, ValidationRuleCallable, ValidationRuleName, ValidationRuleParserInterface, ValidationRuleSet, ValidationServiceProvider, ValidationValueInspector, Validator, ValidatorPlugin, ValidatorPluginApi, addImplicitRule, buildValidationMethodName, compare, convertValuesToBoolean, convertValuesToNull, convertValuesToNumber, deepEqual, deepFind, deepFindMessage, deepSet, definePlugin, dotify, getFormattedAttribute, getKeyCombinations, getMessage, getNumericRules, getSize, getValidationMessageType, getValidationSize, getValidationValueInspector, getValidatorContext, isArrayOfRules, isImplicitRule, isInteger, isNumericRule, isObject, isRule, isSizeRule, make, mergeDeep, notRegex, plural, regex, register, registerImplicit, registerValueInspector, requiredIf, ruleIn, ruleNotIn, runWithValidatorContext, sameType, toDate, toSnakeCase, usePlugin, useValidatorContext };
|
|
1627
|
+
export { BaseValidationRuleClass, BaseValidator, CustomAttributes, CustomErrors, CustomMessages, CustomParamableValidationRuleName, CustomPlainRuleName, CustomValidationRuleNameMap, CustomValidationRules, DotPaths, ErrorBag, ErrorMessage, Errors, ExtendedRules, ExtractRules, FieldMessages, GenericCallable, GenericObject, IDatabaseDriver, IMessageBag, IValidationRule, IValidator, ImplicitAttributes, ImplicitRule, InitialRule, InitialRules, Lang, MessageBag, Messages, MessagesForRules, NestedStringMap, ParamableValidationRuleName, Password, PlainRuleName, ReplaceAttributeInterface, Rules, RulesForData, TRule, ValidatedByRules, ValidationCallback, ValidationDataInterface, ValidationDatabaseExistsInput, ValidationException, ValidationMessageProvider, ValidationRule, ValidationRuleAutocompleteKind, ValidationRuleAutocompleteMap, ValidationRuleCallable, ValidationRuleEntry, ValidationRuleName, ValidationRuleParserInterface, ValidationRuleSet, ValidationServiceProvider, ValidationValueInspector, Validator, ValidatorPlugin, ValidatorPluginApi, addImplicitRule, buildValidationMethodName, compare, convertValuesToBoolean, convertValuesToNull, convertValuesToNumber, deepEqual, deepFind, deepFindMessage, deepSet, definePlugin, dotify, getFormattedAttribute, getKeyCombinations, getMessage, getNumericRules, getSize, getValidationMessageType, getValidationSize, getValidationValueInspector, getValidatorContext, isArrayOfRules, isImplicitRule, isInteger, isNumericRule, isObject, isRule, isSizeRule, make, mergeDeep, notRegex, plural, regex, register, registerImplicit, registerValueInspector, requiredIf, ruleIn, ruleNotIn, runWithValidatorContext, sameType, toDate, toSnakeCase, usePlugin, useValidatorContext };
|
package/dist/index.js
CHANGED
|
@@ -2325,7 +2325,7 @@ var BaseValidator = class BaseValidator {
|
|
|
2325
2325
|
[rule, parameters] = validationRuleParser.parse(rule);
|
|
2326
2326
|
const keys = this.getExplicitKeys(attribute);
|
|
2327
2327
|
if (keys.length > 0 && parameters.length > 0) parameters = this.replaceAsterisksInParameters(parameters, keys);
|
|
2328
|
-
const value =
|
|
2328
|
+
const value = this.getAttributeValue(attribute);
|
|
2329
2329
|
const validatable = this.isValidatable(attribute, value, rule);
|
|
2330
2330
|
if (rule instanceof IRuleContract) return validatable ? this.validateUsingCustomRule(attribute, value, rule) : void 0;
|
|
2331
2331
|
const method = `validate${buildValidationMethodName(rule)}`;
|
|
@@ -2393,14 +2393,14 @@ var BaseValidator = class BaseValidator {
|
|
|
2393
2393
|
* Determine if the attribute is validatable.
|
|
2394
2394
|
*/
|
|
2395
2395
|
isValidatable(attribute, value, rule) {
|
|
2396
|
-
return this.presentOrRuleIsImplicit(attribute, value, rule) && this.passesOptionalCheck(attribute) && this.isNotNullIfMarkedAsNullable(attribute, rule);
|
|
2396
|
+
return this.presentOrRuleIsImplicit(attribute, value, rule) && this.passesOptionalCheck(attribute) && this.isNotNullIfMarkedAsNullable(attribute, value, rule);
|
|
2397
2397
|
}
|
|
2398
2398
|
/**
|
|
2399
2399
|
* Determine if the field is present, or the rule implies required.
|
|
2400
2400
|
*/
|
|
2401
2401
|
presentOrRuleIsImplicit(attribute, value, rule) {
|
|
2402
2402
|
if (typeof value === "string" && value.trim() === "") return isImplicitRule(rule);
|
|
2403
|
-
return typeof
|
|
2403
|
+
return typeof value !== "undefined" || isImplicitRule(rule);
|
|
2404
2404
|
}
|
|
2405
2405
|
/**
|
|
2406
2406
|
* Determine if the attribute passes any optional check.
|
|
@@ -2408,14 +2408,23 @@ var BaseValidator = class BaseValidator {
|
|
|
2408
2408
|
passesOptionalCheck(attribute) {
|
|
2409
2409
|
if (!validationRuleParser.hasRule(attribute, ["sometimes"], this.rules)) return true;
|
|
2410
2410
|
const data = validationData.initializeAndGatherData(attribute, this.data);
|
|
2411
|
-
|
|
2411
|
+
const requestFiles = validationData.initializeAndGatherData(attribute, this.getContext().requestFiles ?? {});
|
|
2412
|
+
return Object.prototype.hasOwnProperty.call(data, attribute) || Object.prototype.hasOwnProperty.call(this.data, attribute) || Object.prototype.hasOwnProperty.call(requestFiles, attribute) || Object.prototype.hasOwnProperty.call(this.getContext().requestFiles ?? {}, attribute);
|
|
2412
2413
|
}
|
|
2413
2414
|
/**
|
|
2414
2415
|
* Determine if the attribute fails the nullable check.
|
|
2415
2416
|
*/
|
|
2416
|
-
isNotNullIfMarkedAsNullable(attribute, rule) {
|
|
2417
|
+
isNotNullIfMarkedAsNullable(attribute, value, rule) {
|
|
2417
2418
|
if (isImplicitRule(rule) || !validationRuleParser.hasRule(attribute, ["nullable"], this.rules)) return true;
|
|
2418
|
-
return
|
|
2419
|
+
return value !== null;
|
|
2420
|
+
}
|
|
2421
|
+
/**
|
|
2422
|
+
* Resolve an attribute value from validator data first, then request-scoped file context.
|
|
2423
|
+
*/
|
|
2424
|
+
getAttributeValue(attribute) {
|
|
2425
|
+
const dataValue = deepFind(this.data, attribute);
|
|
2426
|
+
if (typeof dataValue !== "undefined") return dataValue;
|
|
2427
|
+
return deepFind(this.getContext().requestFiles ?? {}, attribute);
|
|
2419
2428
|
}
|
|
2420
2429
|
/**
|
|
2421
2430
|
* Get the primary attribute name
|