mobx-formkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +761 -0
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/lib/ArrayMap.d.ts +50 -0
- package/lib/ArrayMap.d.ts.map +1 -0
- package/lib/ArrayMap.js +151 -0
- package/lib/ArrayMap.js.map +1 -0
- package/lib/Base.d.ts +237 -0
- package/lib/Base.d.ts.map +1 -0
- package/lib/Base.js +872 -0
- package/lib/Base.js.map +1 -0
- package/lib/Bindings.d.ts +28 -0
- package/lib/Bindings.d.ts.map +1 -0
- package/lib/Bindings.js +73 -0
- package/lib/Bindings.js.map +1 -0
- package/lib/Field.d.ts +195 -0
- package/lib/Field.d.ts.map +1 -0
- package/lib/Field.js +734 -0
- package/lib/Field.js.map +1 -0
- package/lib/Form.d.ts +75 -0
- package/lib/Form.d.ts.map +1 -0
- package/lib/Form.js +199 -0
- package/lib/Form.js.map +1 -0
- package/lib/Options.d.ts +9 -0
- package/lib/Options.d.ts.map +1 -0
- package/lib/Options.js +85 -0
- package/lib/Options.js.map +1 -0
- package/lib/State.d.ts +43 -0
- package/lib/State.d.ts.map +1 -0
- package/lib/State.js +147 -0
- package/lib/State.js.map +1 -0
- package/lib/Validator.d.ts +25 -0
- package/lib/Validator.d.ts.map +1 -0
- package/lib/Validator.js +143 -0
- package/lib/Validator.js.map +1 -0
- package/lib/compat.d.ts +29 -0
- package/lib/compat.d.ts.map +1 -0
- package/lib/compat.js +117 -0
- package/lib/compat.js.map +1 -0
- package/lib/composer.d.ts +26 -0
- package/lib/composer.d.ts.map +1 -0
- package/lib/composer.js +65 -0
- package/lib/composer.js.map +1 -0
- package/lib/esm/ArrayMap.js +146 -0
- package/lib/esm/ArrayMap.js.map +1 -0
- package/lib/esm/Base.js +868 -0
- package/lib/esm/Base.js.map +1 -0
- package/lib/esm/Bindings.js +69 -0
- package/lib/esm/Bindings.js.map +1 -0
- package/lib/esm/Field.js +730 -0
- package/lib/esm/Field.js.map +1 -0
- package/lib/esm/Form.js +195 -0
- package/lib/esm/Form.js.map +1 -0
- package/lib/esm/Options.js +81 -0
- package/lib/esm/Options.js.map +1 -0
- package/lib/esm/State.js +143 -0
- package/lib/esm/State.js.map +1 -0
- package/lib/esm/Validator.js +139 -0
- package/lib/esm/Validator.js.map +1 -0
- package/lib/esm/compat.js +96 -0
- package/lib/esm/compat.js.map +1 -0
- package/lib/esm/composer.js +63 -0
- package/lib/esm/composer.js.map +1 -0
- package/lib/esm/index.js +8 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/models/FieldProps.js +116 -0
- package/lib/esm/models/FieldProps.js.map +1 -0
- package/lib/esm/models/OptionsModel.js +51 -0
- package/lib/esm/models/OptionsModel.js.map +1 -0
- package/lib/esm/models/StateInterface.js +9 -0
- package/lib/esm/models/StateInterface.js.map +1 -0
- package/lib/esm/models/ValidatorInterface.js +8 -0
- package/lib/esm/models/ValidatorInterface.js.map +1 -0
- package/lib/esm/parser.js +235 -0
- package/lib/esm/parser.js.map +1 -0
- package/lib/esm/props.js +118 -0
- package/lib/esm/props.js.map +1 -0
- package/lib/esm/utils.js +156 -0
- package/lib/esm/utils.js.map +1 -0
- package/lib/esm/validators/AJV.js +105 -0
- package/lib/esm/validators/AJV.js.map +1 -0
- package/lib/esm/validators/DVR.js +104 -0
- package/lib/esm/validators/DVR.js.map +1 -0
- package/lib/esm/validators/JOI.js +54 -0
- package/lib/esm/validators/JOI.js.map +1 -0
- package/lib/esm/validators/VALIBOT.js +50 -0
- package/lib/esm/validators/VALIBOT.js.map +1 -0
- package/lib/esm/validators/VINEJS.js +60 -0
- package/lib/esm/validators/VINEJS.js.map +1 -0
- package/lib/esm/validators/VJF.js +88 -0
- package/lib/esm/validators/VJF.js.map +1 -0
- package/lib/esm/validators/YUP.js +69 -0
- package/lib/esm/validators/YUP.js.map +1 -0
- package/lib/esm/validators/ZOD.js +43 -0
- package/lib/esm/validators/ZOD.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +15 -0
- package/lib/index.js.map +1 -0
- package/lib/models/BaseInterface.d.ts +40 -0
- package/lib/models/BaseInterface.d.ts.map +1 -0
- package/lib/models/BindingsInterface.d.ts +18 -0
- package/lib/models/BindingsInterface.d.ts.map +1 -0
- package/lib/models/FieldInterface.d.ts +88 -0
- package/lib/models/FieldInterface.d.ts.map +1 -0
- package/lib/models/FieldProps.d.ts +111 -0
- package/lib/models/FieldProps.d.ts.map +1 -0
- package/lib/models/FieldProps.js +116 -0
- package/lib/models/FieldProps.js.map +1 -0
- package/lib/models/FormInterface.d.ts +184 -0
- package/lib/models/FormInterface.d.ts.map +1 -0
- package/lib/models/OptionsInterface.d.ts +8 -0
- package/lib/models/OptionsInterface.d.ts.map +1 -0
- package/lib/models/OptionsModel.d.ts +99 -0
- package/lib/models/OptionsModel.d.ts.map +1 -0
- package/lib/models/OptionsModel.js +51 -0
- package/lib/models/OptionsModel.js.map +1 -0
- package/lib/models/SharedActionsInterface.d.ts +27 -0
- package/lib/models/SharedActionsInterface.d.ts.map +1 -0
- package/lib/models/SharedEventsInterface.d.ts +8 -0
- package/lib/models/SharedEventsInterface.d.ts.map +1 -0
- package/lib/models/SharedHelpersInterface.d.ts +26 -0
- package/lib/models/SharedHelpersInterface.d.ts.map +1 -0
- package/lib/models/SharedInitializerInterface.d.ts +6 -0
- package/lib/models/SharedInitializerInterface.d.ts.map +1 -0
- package/lib/models/SharedUtilsInterface.d.ts +10 -0
- package/lib/models/SharedUtilsInterface.d.ts.map +1 -0
- package/lib/models/StateInterface.d.ts +37 -0
- package/lib/models/StateInterface.d.ts.map +1 -0
- package/lib/models/StateInterface.js +9 -0
- package/lib/models/StateInterface.js.map +1 -0
- package/lib/models/ValidatorInterface.d.ts +74 -0
- package/lib/models/ValidatorInterface.d.ts.map +1 -0
- package/lib/models/ValidatorInterface.js +8 -0
- package/lib/models/ValidatorInterface.js.map +1 -0
- package/lib/parser.d.ts +13 -0
- package/lib/parser.d.ts.map +1 -0
- package/lib/parser.js +247 -0
- package/lib/parser.js.map +1 -0
- package/lib/props.d.ts +14 -0
- package/lib/props.d.ts.map +1 -0
- package/lib/props.js +120 -0
- package/lib/props.js.map +1 -0
- package/lib/utils.d.ts +34 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +182 -0
- package/lib/utils.js.map +1 -0
- package/lib/validators/AJV.d.ts +4 -0
- package/lib/validators/AJV.d.ts.map +1 -0
- package/lib/validators/AJV.js +109 -0
- package/lib/validators/AJV.js.map +1 -0
- package/lib/validators/DVR.d.ts +4 -0
- package/lib/validators/DVR.d.ts.map +1 -0
- package/lib/validators/DVR.js +108 -0
- package/lib/validators/DVR.js.map +1 -0
- package/lib/validators/JOI.d.ts +4 -0
- package/lib/validators/JOI.d.ts.map +1 -0
- package/lib/validators/JOI.js +58 -0
- package/lib/validators/JOI.js.map +1 -0
- package/lib/validators/VALIBOT.d.ts +4 -0
- package/lib/validators/VALIBOT.d.ts.map +1 -0
- package/lib/validators/VALIBOT.js +73 -0
- package/lib/validators/VALIBOT.js.map +1 -0
- package/lib/validators/VINEJS.d.ts +4 -0
- package/lib/validators/VINEJS.d.ts.map +1 -0
- package/lib/validators/VINEJS.js +64 -0
- package/lib/validators/VINEJS.js.map +1 -0
- package/lib/validators/VJF.d.ts +4 -0
- package/lib/validators/VJF.d.ts.map +1 -0
- package/lib/validators/VJF.js +92 -0
- package/lib/validators/VJF.js.map +1 -0
- package/lib/validators/YUP.d.ts +4 -0
- package/lib/validators/YUP.d.ts.map +1 -0
- package/lib/validators/YUP.js +73 -0
- package/lib/validators/YUP.js.map +1 -0
- package/lib/validators/ZOD.d.ts +4 -0
- package/lib/validators/ZOD.d.ts.map +1 -0
- package/lib/validators/ZOD.js +47 -0
- package/lib/validators/ZOD.js.map +1 -0
- package/package.json +183 -0
- package/src/ArrayMap.ts +165 -0
- package/src/Base.ts +1229 -0
- package/src/Bindings.ts +85 -0
- package/src/Field.ts +1034 -0
- package/src/Form.ts +264 -0
- package/src/Options.ts +91 -0
- package/src/State.ts +183 -0
- package/src/Validator.ts +177 -0
- package/src/compat.ts +104 -0
- package/src/composer.ts +82 -0
- package/src/index.ts +7 -0
- package/src/models/BaseInterface.ts +45 -0
- package/src/models/BindingsInterface.ts +25 -0
- package/src/models/FieldInterface.ts +97 -0
- package/src/models/FieldProps.ts +116 -0
- package/src/models/FormInterface.ts +203 -0
- package/src/models/OptionsInterface.ts +9 -0
- package/src/models/OptionsModel.ts +100 -0
- package/src/models/SharedActionsInterface.ts +30 -0
- package/src/models/SharedEventsInterface.ts +8 -0
- package/src/models/SharedHelpersInterface.ts +12 -0
- package/src/models/SharedInitializerInterface.ts +6 -0
- package/src/models/SharedUtilsInterface.ts +10 -0
- package/src/models/StateInterface.ts +44 -0
- package/src/models/ValidatorInterface.ts +88 -0
- package/src/parser.ts +327 -0
- package/src/props.ts +127 -0
- package/src/utils.ts +218 -0
- package/src/validators/AJV.ts +140 -0
- package/src/validators/DVR.ts +145 -0
- package/src/validators/JOI.ts +79 -0
- package/src/validators/VALIBOT.ts +70 -0
- package/src/validators/VINEJS.ts +83 -0
- package/src/validators/VJF.ts +123 -0
- package/src/validators/YUP.ts +90 -0
- package/src/validators/ZOD.ts +66 -0
- package/umd/MobxFormkit.umd.js +3093 -0
- package/umd/MobxFormkit.umd.js.map +1 -0
- package/umd/MobxFormkit.umd.min.js +2 -0
- package/umd/MobxFormkit.umd.min.js.map +1 -0
- package/umd/MobxFormkitComposer.umd.js +183 -0
- package/umd/MobxFormkitComposer.umd.js.map +1 -0
- package/umd/MobxFormkitComposer.umd.min.js +2 -0
- package/umd/MobxFormkitComposer.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorAJV.umd.js +113 -0
- package/umd/MobxFormkitValidatorAJV.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorAJV.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorAJV.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorDVR.umd.js +110 -0
- package/umd/MobxFormkitValidatorDVR.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorDVR.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorDVR.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorJOI.umd.js +62 -0
- package/umd/MobxFormkitValidatorJOI.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorJOI.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorJOI.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorVALIBOT.umd.js +8032 -0
- package/umd/MobxFormkitValidatorVALIBOT.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorVALIBOT.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorVALIBOT.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorVINEJS.umd.js +11737 -0
- package/umd/MobxFormkitValidatorVINEJS.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorVINEJS.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorVINEJS.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorVJF.umd.js +96 -0
- package/umd/MobxFormkitValidatorVJF.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorVJF.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorVJF.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorYUP.umd.js +77 -0
- package/umd/MobxFormkitValidatorYUP.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorYUP.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorYUP.umd.min.js.map +1 -0
- package/umd/MobxFormkitValidatorZOD.umd.js +49 -0
- package/umd/MobxFormkitValidatorZOD.umd.js.map +1 -0
- package/umd/MobxFormkitValidatorZOD.umd.min.js +2 -0
- package/umd/MobxFormkitValidatorZOD.umd.min.js.map +1 -0
package/src/props.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { FieldPropsEnum, FieldPropsOccurrence, SeparatedPropsMode } from "./models/FieldProps";
|
|
2
|
+
|
|
3
|
+
export interface PropsGroupsInterface {
|
|
4
|
+
editable: string[];
|
|
5
|
+
handlers: string[];
|
|
6
|
+
computed: string[];
|
|
7
|
+
functions: string[];
|
|
8
|
+
validation: string[];
|
|
9
|
+
separated: string[];
|
|
10
|
+
occurrences: {
|
|
11
|
+
[index: string]: FieldPropsOccurrence;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const props: PropsGroupsInterface = {
|
|
16
|
+
editable: [
|
|
17
|
+
FieldPropsEnum.type,
|
|
18
|
+
FieldPropsEnum.value,
|
|
19
|
+
FieldPropsEnum.initial,
|
|
20
|
+
FieldPropsEnum.default,
|
|
21
|
+
FieldPropsEnum.label,
|
|
22
|
+
FieldPropsEnum.placeholder,
|
|
23
|
+
FieldPropsEnum.related,
|
|
24
|
+
FieldPropsEnum.options,
|
|
25
|
+
FieldPropsEnum.extra,
|
|
26
|
+
FieldPropsEnum.bindings,
|
|
27
|
+
FieldPropsEnum.hooks,
|
|
28
|
+
FieldPropsEnum.handlers,
|
|
29
|
+
FieldPropsEnum.deleted,
|
|
30
|
+
FieldPropsEnum.disabled,
|
|
31
|
+
FieldPropsEnum.autoFocus,
|
|
32
|
+
FieldPropsEnum.inputMode,
|
|
33
|
+
FieldPropsEnum.ref,
|
|
34
|
+
FieldPropsEnum.nullable,
|
|
35
|
+
FieldPropsEnum.autoComplete,
|
|
36
|
+
],
|
|
37
|
+
handlers: [
|
|
38
|
+
FieldPropsEnum.onChange,
|
|
39
|
+
FieldPropsEnum.onToggle,
|
|
40
|
+
FieldPropsEnum.onFocus,
|
|
41
|
+
FieldPropsEnum.onBlur,
|
|
42
|
+
FieldPropsEnum.onDrop,
|
|
43
|
+
FieldPropsEnum.onSubmit,
|
|
44
|
+
FieldPropsEnum.onReset,
|
|
45
|
+
FieldPropsEnum.onClear,
|
|
46
|
+
FieldPropsEnum.onAdd,
|
|
47
|
+
FieldPropsEnum.onDel,
|
|
48
|
+
],
|
|
49
|
+
computed: [
|
|
50
|
+
FieldPropsEnum.error,
|
|
51
|
+
FieldPropsEnum.hasError,
|
|
52
|
+
FieldPropsEnum.isValid,
|
|
53
|
+
FieldPropsEnum.isDirty,
|
|
54
|
+
FieldPropsEnum.isPristine,
|
|
55
|
+
FieldPropsEnum.isDefault,
|
|
56
|
+
FieldPropsEnum.isEmpty,
|
|
57
|
+
FieldPropsEnum.focused,
|
|
58
|
+
FieldPropsEnum.touched,
|
|
59
|
+
FieldPropsEnum.changed,
|
|
60
|
+
FieldPropsEnum.validating,
|
|
61
|
+
FieldPropsEnum.submitting,
|
|
62
|
+
FieldPropsEnum.resetting,
|
|
63
|
+
FieldPropsEnum.clearing,
|
|
64
|
+
FieldPropsEnum.blurred,
|
|
65
|
+
FieldPropsEnum.deleted,
|
|
66
|
+
FieldPropsEnum.disabled,
|
|
67
|
+
],
|
|
68
|
+
separated: [
|
|
69
|
+
SeparatedPropsMode.computed,
|
|
70
|
+
SeparatedPropsMode.values,
|
|
71
|
+
SeparatedPropsMode.labels,
|
|
72
|
+
SeparatedPropsMode.placeholders,
|
|
73
|
+
SeparatedPropsMode.defaults,
|
|
74
|
+
SeparatedPropsMode.initials,
|
|
75
|
+
SeparatedPropsMode.disabled,
|
|
76
|
+
SeparatedPropsMode.deleted,
|
|
77
|
+
SeparatedPropsMode.types,
|
|
78
|
+
SeparatedPropsMode.related,
|
|
79
|
+
SeparatedPropsMode.rules,
|
|
80
|
+
SeparatedPropsMode.options,
|
|
81
|
+
SeparatedPropsMode.bindings,
|
|
82
|
+
SeparatedPropsMode.extra,
|
|
83
|
+
SeparatedPropsMode.hooks,
|
|
84
|
+
SeparatedPropsMode.handlers,
|
|
85
|
+
SeparatedPropsMode.validatedWith,
|
|
86
|
+
SeparatedPropsMode.validators,
|
|
87
|
+
SeparatedPropsMode.observers,
|
|
88
|
+
SeparatedPropsMode.interceptors,
|
|
89
|
+
SeparatedPropsMode.converters,
|
|
90
|
+
SeparatedPropsMode.input,
|
|
91
|
+
SeparatedPropsMode.output,
|
|
92
|
+
SeparatedPropsMode.autoFocus,
|
|
93
|
+
SeparatedPropsMode.inputMode,
|
|
94
|
+
SeparatedPropsMode.refs,
|
|
95
|
+
SeparatedPropsMode.classes,
|
|
96
|
+
SeparatedPropsMode.nullable,
|
|
97
|
+
SeparatedPropsMode.autoComplete,
|
|
98
|
+
],
|
|
99
|
+
functions: [
|
|
100
|
+
FieldPropsEnum.computed,
|
|
101
|
+
FieldPropsEnum.observers,
|
|
102
|
+
FieldPropsEnum.interceptors,
|
|
103
|
+
FieldPropsEnum.converter,
|
|
104
|
+
FieldPropsEnum.input,
|
|
105
|
+
FieldPropsEnum.output,
|
|
106
|
+
],
|
|
107
|
+
validation: [
|
|
108
|
+
FieldPropsEnum.rules,
|
|
109
|
+
FieldPropsEnum.validators,
|
|
110
|
+
FieldPropsEnum.validatedWith,
|
|
111
|
+
],
|
|
112
|
+
occurrences: {
|
|
113
|
+
isDirty: FieldPropsOccurrence.some,
|
|
114
|
+
isPristine: FieldPropsOccurrence.every,
|
|
115
|
+
isDefault: FieldPropsOccurrence.every,
|
|
116
|
+
isValid: FieldPropsOccurrence.every,
|
|
117
|
+
isEmpty: FieldPropsOccurrence.every,
|
|
118
|
+
hasError: FieldPropsOccurrence.some,
|
|
119
|
+
focused: FieldPropsOccurrence.some,
|
|
120
|
+
blurred: FieldPropsOccurrence.some,
|
|
121
|
+
touched: FieldPropsOccurrence.some,
|
|
122
|
+
deleted: FieldPropsOccurrence.every,
|
|
123
|
+
disabled: FieldPropsOccurrence.every,
|
|
124
|
+
clearing: FieldPropsOccurrence.every,
|
|
125
|
+
resetting: FieldPropsOccurrence.every,
|
|
126
|
+
},
|
|
127
|
+
};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { has, isEmpty, isPlainObject } from "lodash";
|
|
2
|
+
import { values as mobxValues, keys as mobxKeys } from "mobx";
|
|
3
|
+
import { FieldInterface } from "./models/FieldInterface";
|
|
4
|
+
import { AllowedFieldPropsTypes, FieldPropsEnum, FieldPropsOccurrence } from "./models/FieldProps";
|
|
5
|
+
import { props } from "./props";
|
|
6
|
+
|
|
7
|
+
const getObservableMapValues = (fields: any):
|
|
8
|
+
ReadonlyArray<FieldInterface> => {
|
|
9
|
+
// ArrayMap duck-typing
|
|
10
|
+
if (fields && fields._isArrayMap) {
|
|
11
|
+
const result: FieldInterface[] = [];
|
|
12
|
+
fields.forEach((value: FieldInterface) => result.push(value));
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
return mobxValues(fields);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const getObservableMapKeys = (fields: any):
|
|
19
|
+
ReadonlyArray<any> => {
|
|
20
|
+
// ArrayMap duck-typing
|
|
21
|
+
if (fields && fields._isArrayMap) {
|
|
22
|
+
return Array.from(fields.keys());
|
|
23
|
+
}
|
|
24
|
+
return mobxKeys(fields);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const checkObserveItem =
|
|
28
|
+
(change: any) =>
|
|
29
|
+
({ key, to, type, exec }: any) =>
|
|
30
|
+
change.type === type &&
|
|
31
|
+
change.name === key &&
|
|
32
|
+
change.newValue === to &&
|
|
33
|
+
exec.apply(change, [change]);
|
|
34
|
+
|
|
35
|
+
const checkObserve = (collection: Record<string, any>[]) => (change: any) =>
|
|
36
|
+
collection.map(checkObserveItem(change));
|
|
37
|
+
|
|
38
|
+
const checkPropOccurrence = ({ type, data }: any): boolean => {
|
|
39
|
+
let $check: any;
|
|
40
|
+
switch (type) {
|
|
41
|
+
case FieldPropsOccurrence.some: $check = ($data: object) => ($data as any[]).some(Boolean); break;
|
|
42
|
+
case FieldPropsOccurrence.every: $check = ($data: object) => ($data as any[]).every(Boolean); break;
|
|
43
|
+
default: throw new Error('Occurrence not found for specified prop');
|
|
44
|
+
}
|
|
45
|
+
return $check(data);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const hasProps = ($type: string, $data: any): boolean => {
|
|
49
|
+
let $props: string[] | null;
|
|
50
|
+
switch ($type) {
|
|
51
|
+
case AllowedFieldPropsTypes.computed:
|
|
52
|
+
$props = props.computed;
|
|
53
|
+
break;
|
|
54
|
+
case AllowedFieldPropsTypes.observable:
|
|
55
|
+
$props = [
|
|
56
|
+
FieldPropsEnum.fields,
|
|
57
|
+
...props.computed,
|
|
58
|
+
...props.editable,
|
|
59
|
+
];
|
|
60
|
+
break;
|
|
61
|
+
case AllowedFieldPropsTypes.editable:
|
|
62
|
+
$props = [
|
|
63
|
+
...props.editable,
|
|
64
|
+
...props.validation,
|
|
65
|
+
...props.functions,
|
|
66
|
+
...props.handlers,
|
|
67
|
+
];
|
|
68
|
+
break;
|
|
69
|
+
case AllowedFieldPropsTypes.all:
|
|
70
|
+
$props = [
|
|
71
|
+
FieldPropsEnum.id,
|
|
72
|
+
FieldPropsEnum.key,
|
|
73
|
+
FieldPropsEnum.name,
|
|
74
|
+
FieldPropsEnum.path,
|
|
75
|
+
...props.computed,
|
|
76
|
+
...props.editable,
|
|
77
|
+
...props.validation,
|
|
78
|
+
...props.functions,
|
|
79
|
+
...props.handlers,
|
|
80
|
+
];
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
$props = null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return $data.filter((x: string) => $props!.includes(x)).length > 0;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
Check Allowed Properties
|
|
91
|
+
*/
|
|
92
|
+
const allowedProps = (type: string, data: string[]): void => {
|
|
93
|
+
if (hasProps(type, data)) return;
|
|
94
|
+
const $msg = "The selected property is not allowed";
|
|
95
|
+
throw new Error(`${$msg} (${JSON.stringify(data)})`);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
Throw Error if undefined Fields
|
|
100
|
+
*/
|
|
101
|
+
const throwError = (path: string, fields: any, msg: null | string = null): void => {
|
|
102
|
+
if (fields != null) return;
|
|
103
|
+
const $msg = msg == null ? "The selected field is not defined" : msg;
|
|
104
|
+
throw new Error(`${$msg} (${path})`);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const pathToStruct = (path: string): string => {
|
|
108
|
+
let struct;
|
|
109
|
+
struct = path.replace(/\.\d+($|\.)/g, "[].");
|
|
110
|
+
struct = struct.replace("..", ".");
|
|
111
|
+
struct = struct.replace(/^\.+|\.+$/g, "");
|
|
112
|
+
return struct;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const isArrayFromStruct = (struct: string[], structPath: string): boolean => {
|
|
116
|
+
if (isArrayOfStrings(struct)) return !!struct
|
|
117
|
+
.filter((s) => s.startsWith(structPath))
|
|
118
|
+
.find((s) => s.substring(structPath.length) === "[]")
|
|
119
|
+
|| (struct?.find((e) => e === structPath)?.endsWith('[]') ?? false);
|
|
120
|
+
else return false;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const hasSome = (obj: any, keys: any): boolean =>
|
|
124
|
+
keys.some((key: string) => has(obj, key));
|
|
125
|
+
|
|
126
|
+
const isEmptyArray = (field: any): boolean =>
|
|
127
|
+
isEmpty(field) && Array.isArray(field);
|
|
128
|
+
|
|
129
|
+
const isArrayOfStrings = (struct: any): boolean =>
|
|
130
|
+
Array.isArray(struct) && struct.every((s: any) => typeof s === 'string');
|
|
131
|
+
|
|
132
|
+
const isArrayOfObjects = (fields: any): boolean =>
|
|
133
|
+
Array.isArray(fields) && fields.every((f: any) => isPlainObject(f));
|
|
134
|
+
|
|
135
|
+
const getKeys = (fields: any) =>
|
|
136
|
+
fields ? [...new Set(Object.values(fields).flatMap((values) => values ? Object.keys(values) : []))] : [];
|
|
137
|
+
|
|
138
|
+
const hasUnifiedProps = ({ fields }: any) =>
|
|
139
|
+
!isArrayOfStrings({ fields }) && hasProps(AllowedFieldPropsTypes.editable, getKeys(fields));
|
|
140
|
+
|
|
141
|
+
const hasSeparatedProps = (initial: any): boolean =>
|
|
142
|
+
hasSome(initial, props.separated) || hasSome(initial, props.validation);
|
|
143
|
+
|
|
144
|
+
const allowNested = (field: any, strictProps: boolean): boolean =>
|
|
145
|
+
field !== null && typeof field === 'object' &&
|
|
146
|
+
!(field instanceof Date) &&
|
|
147
|
+
!has(field, FieldPropsEnum.fields) &&
|
|
148
|
+
!has(field, FieldPropsEnum.class) &&
|
|
149
|
+
(!hasSome(field, [
|
|
150
|
+
...props.editable,
|
|
151
|
+
...props.handlers,
|
|
152
|
+
...props.validation,
|
|
153
|
+
...props.functions,
|
|
154
|
+
]) || strictProps);
|
|
155
|
+
|
|
156
|
+
const parseIntKeys = (fields: any) =>
|
|
157
|
+
Array.from(getObservableMapKeys(fields)).map(Number);
|
|
158
|
+
|
|
159
|
+
const hasIntKeys = (fields: any): boolean =>
|
|
160
|
+
parseIntKeys(fields).every((x: any) => Number.isInteger(x));
|
|
161
|
+
|
|
162
|
+
const maxKey = (fields: any): number => {
|
|
163
|
+
const keys = parseIntKeys(fields);
|
|
164
|
+
const maxVal = keys.length ? Math.max(...keys) : undefined;
|
|
165
|
+
return maxVal === void 0 ? 0 : maxVal + 1;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
let _idCounter = 0;
|
|
169
|
+
const _localUniqueId = (prefix: string): string => `${prefix}${++_idCounter}`;
|
|
170
|
+
|
|
171
|
+
const uniqueId = (field: any): string =>
|
|
172
|
+
_localUniqueId([field.path.replace(/\./g, "-"), "--"].join(""));
|
|
173
|
+
|
|
174
|
+
const isEvent = (obj: any): boolean => {
|
|
175
|
+
if (obj == null || typeof Event === "undefined") return false;
|
|
176
|
+
return obj instanceof Event || obj.target != null;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const hasFiles = ($: any): boolean =>
|
|
180
|
+
!!$?.target?.files && $.target.files.length !== 0;
|
|
181
|
+
|
|
182
|
+
const isBool = ($: any, val: any): boolean =>
|
|
183
|
+
typeof val === 'boolean' && typeof $.target.checked === 'boolean';
|
|
184
|
+
|
|
185
|
+
const $try = (...args: any[]) => {
|
|
186
|
+
for (const val of args) {
|
|
187
|
+
if (val !== undefined) return val;
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export {
|
|
193
|
+
props,
|
|
194
|
+
checkObserve,
|
|
195
|
+
checkPropOccurrence,
|
|
196
|
+
hasProps,
|
|
197
|
+
allowedProps,
|
|
198
|
+
throwError,
|
|
199
|
+
isArrayOfStrings,
|
|
200
|
+
isEmptyArray,
|
|
201
|
+
isArrayOfObjects,
|
|
202
|
+
pathToStruct,
|
|
203
|
+
isArrayFromStruct,
|
|
204
|
+
hasUnifiedProps,
|
|
205
|
+
hasSeparatedProps,
|
|
206
|
+
allowNested,
|
|
207
|
+
parseIntKeys,
|
|
208
|
+
hasIntKeys,
|
|
209
|
+
maxKey,
|
|
210
|
+
uniqueId,
|
|
211
|
+
isEvent,
|
|
212
|
+
hasFiles,
|
|
213
|
+
isBool,
|
|
214
|
+
hasSome,
|
|
215
|
+
$try,
|
|
216
|
+
getObservableMapKeys,
|
|
217
|
+
getObservableMapValues,
|
|
218
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
|
|
2
|
+
import FieldInterface from "../models/FieldInterface";
|
|
3
|
+
import FormInterface from "../models/FormInterface";
|
|
4
|
+
import StateInterface from "../models/StateInterface";
|
|
5
|
+
import {
|
|
6
|
+
ValidationPlugin,
|
|
7
|
+
ValidationPluginConfig,
|
|
8
|
+
ValidationPluginConstructor,
|
|
9
|
+
ValidationPluginInterface,
|
|
10
|
+
} from "../models/ValidatorInterface";
|
|
11
|
+
|
|
12
|
+
function isPromise(obj: any): obj is Promise<any> {
|
|
13
|
+
return (
|
|
14
|
+
!!obj &&
|
|
15
|
+
typeof obj.then === "function" &&
|
|
16
|
+
(typeof obj === "object" || typeof obj === "function")
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class AJV<TValidator = any> implements ValidationPluginInterface<TValidator> {
|
|
21
|
+
promises: Promise<any>[];
|
|
22
|
+
config: ValidationPluginConfig<TValidator>;
|
|
23
|
+
state: StateInterface | null;
|
|
24
|
+
extend?: (args: { validator: TValidator; form: FormInterface }) => void;
|
|
25
|
+
validator: any;
|
|
26
|
+
schema: any;
|
|
27
|
+
|
|
28
|
+
constructor({
|
|
29
|
+
config,
|
|
30
|
+
state = null,
|
|
31
|
+
promises = [],
|
|
32
|
+
}: ValidationPluginConstructor<TValidator>) {
|
|
33
|
+
this.state = state;
|
|
34
|
+
this.promises = promises;
|
|
35
|
+
this.config = config;
|
|
36
|
+
this.extend = config?.extend;
|
|
37
|
+
this.schema = config.schema;
|
|
38
|
+
this.initValidator();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
extendOptions(options: any = {}) {
|
|
42
|
+
return {
|
|
43
|
+
...options,
|
|
44
|
+
allErrors: true,
|
|
45
|
+
coerceTypes: true,
|
|
46
|
+
strict: false,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
initValidator(): void {
|
|
51
|
+
const AjvPackage = this.config.package as any;
|
|
52
|
+
const validatorInstance = new AjvPackage(this.extendOptions(this.config.options));
|
|
53
|
+
|
|
54
|
+
if (typeof validatorInstance.addFormat === "function") {
|
|
55
|
+
validatorInstance.addFormat("email", (value: any) =>
|
|
56
|
+
typeof value === "string"
|
|
57
|
+
? /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
|
|
58
|
+
: false
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (typeof this.extend === "function") {
|
|
63
|
+
this.extend({
|
|
64
|
+
form: this.state!.form,
|
|
65
|
+
validator: validatorInstance,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.validator = validatorInstance.compile(this.schema);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
validate(field: FieldInterface): void {
|
|
73
|
+
let result: any;
|
|
74
|
+
try {
|
|
75
|
+
result = this.validator(field.state.form.flatMapValues);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (isPromise(result)) {
|
|
81
|
+
const $p = result
|
|
82
|
+
.then(() => field.setValidationAsyncData(true))
|
|
83
|
+
.catch((err) => err && this.handleAsyncError(field, err.errors))
|
|
84
|
+
.then(() => this.executeAsyncValidation(field));
|
|
85
|
+
|
|
86
|
+
this.promises.push($p);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.handleSyncError(field, this.validator.errors);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
handleSyncError(field: FieldInterface, errors: any[]): void {
|
|
94
|
+
const fieldError = this.findError(field.path ?? '', errors);
|
|
95
|
+
if (!fieldError) return;
|
|
96
|
+
|
|
97
|
+
const message = `${field.label} ${fieldError.message}`;
|
|
98
|
+
field.invalidate(message, false);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
handleAsyncError(field: FieldInterface, errors: any[]): void {
|
|
102
|
+
const fieldError = this.findError(field.path ?? '', errors);
|
|
103
|
+
if (!fieldError) return;
|
|
104
|
+
|
|
105
|
+
const message = `${field.label} ${fieldError.message}`;
|
|
106
|
+
field.setValidationAsyncData(false, message);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
normalizePath(value: any): string {
|
|
110
|
+
return String(value)
|
|
111
|
+
.replace(/^[./]+/, "")
|
|
112
|
+
.replace(/\]/g, "")
|
|
113
|
+
.replace(/\[/g, ".")
|
|
114
|
+
.replace(/\//g, ".");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
findError(path: string, errors: any[]): any {
|
|
118
|
+
if (!errors) return;
|
|
119
|
+
const $path = this.normalizePath(path);
|
|
120
|
+
return errors.find(({ instancePath, dataPath }) => {
|
|
121
|
+
const $dataPath = this.normalizePath(
|
|
122
|
+
typeof instancePath === "string" ? instancePath : dataPath
|
|
123
|
+
);
|
|
124
|
+
return $dataPath.includes($path);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
executeAsyncValidation(field: FieldInterface): void {
|
|
129
|
+
if (field.validationAsyncData.valid === false) {
|
|
130
|
+
field.invalidate(field.validationAsyncData.message ?? undefined, false, true);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export default <TValidator = any>(
|
|
136
|
+
config?: ValidationPluginConfig<TValidator>
|
|
137
|
+
): ValidationPlugin<TValidator> => ({
|
|
138
|
+
class: AJV<TValidator>,
|
|
139
|
+
config,
|
|
140
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { forIn, isEmpty } from "lodash";
|
|
2
|
+
import FieldInterface from "../models/FieldInterface";
|
|
3
|
+
import FormInterface from "../models/FormInterface";
|
|
4
|
+
import StateInterface from "../models/StateInterface";
|
|
5
|
+
import {
|
|
6
|
+
ValidationPlugin,
|
|
7
|
+
ValidationPluginConfig,
|
|
8
|
+
ValidationPluginConstructor,
|
|
9
|
+
ValidationPluginInterface,
|
|
10
|
+
} from "../models/ValidatorInterface";
|
|
11
|
+
|
|
12
|
+
class DVR<TValidator = any>
|
|
13
|
+
implements ValidationPluginInterface<TValidator>
|
|
14
|
+
{
|
|
15
|
+
promises: Promise<any>[];
|
|
16
|
+
config: any;
|
|
17
|
+
state: StateInterface | null;
|
|
18
|
+
extend?: (args: { validator: TValidator; form: FormInterface }) => void;
|
|
19
|
+
validator: TValidator;
|
|
20
|
+
schema?: any;
|
|
21
|
+
|
|
22
|
+
constructor({
|
|
23
|
+
config,
|
|
24
|
+
state = null,
|
|
25
|
+
promises = [],
|
|
26
|
+
}: ValidationPluginConstructor<TValidator>) {
|
|
27
|
+
this.state = state;
|
|
28
|
+
this.promises = promises;
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.extend = config?.extend;
|
|
31
|
+
this.validator = config.package!;
|
|
32
|
+
this.extendValidator();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
extendValidator() {
|
|
36
|
+
if (typeof this.extend === "function") {
|
|
37
|
+
this.extend({
|
|
38
|
+
validator: this.validator,
|
|
39
|
+
form: this.state!.form,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
validate(field: FieldInterface) {
|
|
45
|
+
const data = this.state!.form.flatMapValues;
|
|
46
|
+
this.validateFieldAsync(field, data);
|
|
47
|
+
this.validateFieldSync(field, data);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
makeLabels(validation: any, field: FieldInterface) {
|
|
51
|
+
const labels: Record<string, any> = { [field.path ?? ""]: field.label };
|
|
52
|
+
forIn(validation.rules[field.path ?? ""], (rule) => {
|
|
53
|
+
if (
|
|
54
|
+
typeof rule.value === "string" &&
|
|
55
|
+
rule.name.match(/^(required_|same|different)/)
|
|
56
|
+
) {
|
|
57
|
+
forIn(rule.value.split(","), (p, i: any) => {
|
|
58
|
+
if (!rule.name.match(/^required_(if|unless)/) || i % 2 === 0) {
|
|
59
|
+
const f = this.state!.form.$(p);
|
|
60
|
+
if (f && f.path && f.label) {
|
|
61
|
+
labels[f.path] = f.label;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
} else if (
|
|
66
|
+
typeof rule.value === "string" &&
|
|
67
|
+
rule.name.match(/^(before|after)/)
|
|
68
|
+
) {
|
|
69
|
+
const f = this.state!.form.$(rule.value);
|
|
70
|
+
if (f && f.path && f.label) {
|
|
71
|
+
labels[f.path] = f.label;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
validation.setAttributeNames(labels);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
validateFieldSync(field: FieldInterface, data: any) {
|
|
79
|
+
const $rules = this.rules(field.rules, "sync");
|
|
80
|
+
if (isEmpty($rules[0])) return;
|
|
81
|
+
const rules = { [field.path ?? ""]: $rules };
|
|
82
|
+
const validation = new (this.validator as any)(data, rules);
|
|
83
|
+
this.makeLabels(validation, field);
|
|
84
|
+
if (validation.passes()) return;
|
|
85
|
+
field.invalidate((validation.errors.get(field.path) as any[])[0], false);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
validateFieldAsync(field: FieldInterface, data: any) {
|
|
89
|
+
const $rules = this.rules(field.rules, "async");
|
|
90
|
+
if (isEmpty($rules[0])) return;
|
|
91
|
+
const rules = { [field.path ?? ""]: $rules };
|
|
92
|
+
const validation = new (this.validator as any)(data, rules);
|
|
93
|
+
this.makeLabels(validation, field);
|
|
94
|
+
|
|
95
|
+
const $p = new Promise((resolve: any) =>
|
|
96
|
+
validation.checkAsync(
|
|
97
|
+
() => this.handleAsyncPasses(field, resolve),
|
|
98
|
+
() => this.handleAsyncFails(field, validation, resolve)
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
this.promises.push($p);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
handleAsyncPasses(field: FieldInterface, resolve: () => void) {
|
|
106
|
+
field.setValidationAsyncData(true);
|
|
107
|
+
resolve();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
handleAsyncFails(
|
|
111
|
+
field: FieldInterface,
|
|
112
|
+
validation: any,
|
|
113
|
+
resolve: () => void
|
|
114
|
+
) {
|
|
115
|
+
field.setValidationAsyncData(
|
|
116
|
+
false,
|
|
117
|
+
(validation.errors.get(field.path) as any[])[0]
|
|
118
|
+
);
|
|
119
|
+
this.executeAsyncValidation(field);
|
|
120
|
+
resolve();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
executeAsyncValidation(field: FieldInterface) {
|
|
124
|
+
if (field.validationAsyncData.valid === false) {
|
|
125
|
+
field.invalidate(field.validationAsyncData.message ?? undefined, false, true);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
rules(rules: any, type: "sync" | "async") {
|
|
130
|
+
const $rules = Array.isArray(rules) ? rules : typeof rules === 'string' ? rules.split("|") : [];
|
|
131
|
+
const v = new (this.validator as any)();
|
|
132
|
+
return $rules.filter(($rule: any) =>
|
|
133
|
+
type === "async"
|
|
134
|
+
? v.getRule($rule.split(":")[0])?.async
|
|
135
|
+
: !v.getRule($rule.split(":")[0])?.async
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default <TValidator = any>(
|
|
141
|
+
config?: ValidationPluginConfig<TValidator>
|
|
142
|
+
): ValidationPlugin<TValidator> => ({
|
|
143
|
+
class: DVR<TValidator>,
|
|
144
|
+
config,
|
|
145
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import FieldInterface from "../models/FieldInterface";
|
|
2
|
+
import FormInterface from "../models/FormInterface";
|
|
3
|
+
import StateInterface from "../models/StateInterface";
|
|
4
|
+
import {
|
|
5
|
+
ValidationPlugin,
|
|
6
|
+
ValidationPluginConfig,
|
|
7
|
+
ValidationPluginConstructor,
|
|
8
|
+
ValidationPluginInterface,
|
|
9
|
+
} from "../models/ValidatorInterface";
|
|
10
|
+
|
|
11
|
+
class JOI<TValidator = any> implements ValidationPluginInterface<TValidator> {
|
|
12
|
+
promises: Promise<any>[];
|
|
13
|
+
config: ValidationPluginConfig<TValidator>;
|
|
14
|
+
state: StateInterface | null;
|
|
15
|
+
extend?: (args: { validator: TValidator; form: FormInterface }) => void;
|
|
16
|
+
validator: TValidator;
|
|
17
|
+
schema: any;
|
|
18
|
+
|
|
19
|
+
constructor({
|
|
20
|
+
config,
|
|
21
|
+
state = null,
|
|
22
|
+
promises = [],
|
|
23
|
+
}: ValidationPluginConstructor<TValidator>) {
|
|
24
|
+
this.state = state;
|
|
25
|
+
this.promises = promises;
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.extend = config?.extend;
|
|
28
|
+
this.validator = config.package!;
|
|
29
|
+
this.schema = config.schema;
|
|
30
|
+
this.extendValidator();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
extendValidator(): void {
|
|
34
|
+
if (typeof this.extend === "function") {
|
|
35
|
+
this.extend({
|
|
36
|
+
validator: this.validator,
|
|
37
|
+
form: this.state!.form,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
validate(field: FieldInterface): void {
|
|
43
|
+
const data = this.state!.form.flatMapValues;
|
|
44
|
+
const { error } = this.schema.validate(data, { abortEarly: false });
|
|
45
|
+
|
|
46
|
+
if (!error) return;
|
|
47
|
+
|
|
48
|
+
const fieldPathArray = (field.path ?? "").split(".");
|
|
49
|
+
|
|
50
|
+
const fieldErrors = error.details
|
|
51
|
+
.filter((detail: any) => {
|
|
52
|
+
const errorPathString = detail.path.join(".");
|
|
53
|
+
const fieldPathString = fieldPathArray.join(".");
|
|
54
|
+
return (
|
|
55
|
+
errorPathString === fieldPathString ||
|
|
56
|
+
errorPathString.startsWith(`${fieldPathString}.`)
|
|
57
|
+
);
|
|
58
|
+
})
|
|
59
|
+
.map((detail: any) => {
|
|
60
|
+
const label = detail.context?.label || detail.path.join(".");
|
|
61
|
+
const message = detail.message.replace(
|
|
62
|
+
`${detail.path.join(".")}`,
|
|
63
|
+
label
|
|
64
|
+
);
|
|
65
|
+
return message;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (fieldErrors.length) {
|
|
69
|
+
field.validationErrorStack = fieldErrors;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default <TValidator = any>(
|
|
75
|
+
config?: ValidationPluginConfig<TValidator>
|
|
76
|
+
): ValidationPlugin<TValidator> => ({
|
|
77
|
+
class: JOI<TValidator>,
|
|
78
|
+
config,
|
|
79
|
+
});
|