forked from data-driven-forms/react-forms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidator-helpers.ts
More file actions
117 lines (99 loc) · 3.54 KB
/
validator-helpers.ts
File metadata and controls
117 lines (99 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { memoize } from '../common/helpers';
import { dataTypeValidator } from '../validators/validator-functions';
import composeValidators from '../compose-validators';
import { ValidatorFunction } from '../validators';
import { DataType } from '../data-types';
export interface WarningValidationResult {
type: 'warning';
error: any;
}
export interface ValidatorDefinition {
type: string;
warning?: boolean;
[key: string]: any;
}
export interface ValidatorMapper {
[key: string]: (config: any) => ValidatorFunction;
}
export type MainValidatorMapper = {
[key: string]: ValidatorFunction | ((options?: any) => ValidatorFunction);
};
const isValidatorMapper = (mapper: ValidatorMapper | MainValidatorMapper): mapper is ValidatorMapper => {
// Check if all values are factory functions
return Object.values(mapper).every((value) => {
if (typeof value !== 'function') {
return false;
}
try {
const result = value({});
return typeof result === 'function';
} catch {
return false;
}
});
};
const convertMainValidatorMapper = (mainMapper: MainValidatorMapper): ValidatorMapper => {
const converted: ValidatorMapper = {};
for (const [key, value] of Object.entries(mainMapper)) {
if (typeof value === 'function') {
// Try to determine if it's a factory function or ValidatorFunction
try {
const testResult = value({});
if (typeof testResult === 'function') {
// It's a factory function
converted[key] = value as (config: any) => ValidatorFunction;
} else {
// It's a ValidatorFunction, wrap it
converted[key] = () => value as ValidatorFunction;
}
} catch {
// If calling with {} fails, it's likely a ValidatorFunction
converted[key] = () => value as ValidatorFunction;
}
}
}
return converted;
};
export const convertToWarning =
(validator: ValidatorFunction): ValidatorFunction =>
(...args: Parameters<ValidatorFunction>) => ({
type: 'warning',
error: validator(args[0], args[1], args[2]),
});
export const prepareValidator = (validator: ValidatorDefinition | ValidatorFunction, mapper: ValidatorMapper): ValidatorFunction => {
if (typeof validator === 'function') {
return memoize(validator);
}
if (validator.warning) {
return convertToWarning(mapper[validator.type]({ ...validator }));
}
return mapper[validator.type]({ ...validator });
};
export const getValidate = (
validate?: (ValidatorDefinition | ValidatorFunction)[],
dataType?: DataType,
mapper: ValidatorMapper | MainValidatorMapper = {}
): ValidatorFunction[] => {
const convertedMapper = isValidatorMapper(mapper) ? mapper : convertMainValidatorMapper(mapper as MainValidatorMapper);
return [
...(validate ? validate.map((validator) => prepareValidator(validator, convertedMapper)) : []),
...(dataType ? [dataTypeValidator(dataType)() as unknown as ValidatorFunction] : []),
];
};
export const prepareArrayValidator =
(validation: ValidatorFunction[]) =>
(value: any[] = []): any => {
if (!Array.isArray(value)) {
return;
}
const arrayValidator = composeValidators(validation);
let result = arrayValidator(value && value.length > 0 ? value : undefined);
// Handle both sync and async validation results
if (typeof result === 'function') {
result = (result as Function)(value);
} else if ((result as any)?.then && typeof (result as any).then === 'function') {
// Handle Promise case - return the promise
return result;
}
return result;
};