@nolwenture/formik-jsonschema-form 1.4.3 → 2.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/README.md +188 -1
- package/dist/cjs/Form/fields/ObjectField/ObjectField.js +26 -16
- package/dist/cjs/utils/createValidationSchema.js +142 -6
- package/dist/esm/Form/fields/ObjectField/ObjectField.js +26 -16
- package/dist/esm/utils/createValidationSchema.js +142 -6
- package/dist/types/utils/createValidationSchema.d.ts +10 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -166,7 +166,7 @@ export function MyFormComponent() {
|
|
|
166
166
|
return (
|
|
167
167
|
<Formik
|
|
168
168
|
initialValues={createInitialValues(schema)}
|
|
169
|
-
validationSchema={createValidationSchema(schema)}
|
|
169
|
+
validationSchema={createValidationSchema({schema})}
|
|
170
170
|
onSubmit={handleSubmit}
|
|
171
171
|
>
|
|
172
172
|
<Form schema={schema} uiSchema={uiSchema}></Form>
|
|
@@ -175,6 +175,169 @@ export function MyFormComponent() {
|
|
|
175
175
|
}
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
+
### Validation
|
|
179
|
+
|
|
180
|
+
The `createValidationSchema` function generates a Yup validation schema from your JSON Schema. It supports:
|
|
181
|
+
|
|
182
|
+
#### Supported JSON Schema Keywords
|
|
183
|
+
|
|
184
|
+
**String validation:**
|
|
185
|
+
- `minLength` - Minimum string length
|
|
186
|
+
- `maxLength` - Maximum string length
|
|
187
|
+
- `pattern` - Regular expression pattern
|
|
188
|
+
|
|
189
|
+
**Number validation:**
|
|
190
|
+
- `minimum` - Minimum value (inclusive)
|
|
191
|
+
- `maximum` - Maximum value (inclusive)
|
|
192
|
+
- `exclusiveMinimum` - Minimum value (exclusive)
|
|
193
|
+
- `exclusiveMaximum` - Maximum value (exclusive)
|
|
194
|
+
- `multipleOf` - Value must be a multiple of this number
|
|
195
|
+
|
|
196
|
+
**Array validation:**
|
|
197
|
+
- `minItems` - Minimum number of items
|
|
198
|
+
- `maxItems` - Maximum number of items
|
|
199
|
+
- `uniqueItems` - All items must be unique
|
|
200
|
+
|
|
201
|
+
**Equality validation:**
|
|
202
|
+
- `const` - Value must equal the specified constant
|
|
203
|
+
- `enum` - Value must be one of the specified values
|
|
204
|
+
- `not: { const: ... }` - Value must NOT equal the specified constant
|
|
205
|
+
|
|
206
|
+
**Required fields:**
|
|
207
|
+
- Fields listed in the `required` array are validated as required
|
|
208
|
+
|
|
209
|
+
#### Function Signature
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
createValidationSchema(
|
|
213
|
+
{ schema, uiSchema }, // Schema and optional UI schema
|
|
214
|
+
definitions, // Optional external definitions
|
|
215
|
+
{ localize } // Optional localization function
|
|
216
|
+
)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### Custom Error Messages
|
|
220
|
+
|
|
221
|
+
You can customize error messages using `ui:validation` in the uiSchema:
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
const uiSchema = {
|
|
225
|
+
username: {
|
|
226
|
+
"ui:validation": {
|
|
227
|
+
error: {
|
|
228
|
+
minLength: "Username must be at least 3 characters",
|
|
229
|
+
pattern: "Username can only contain letters and numbers",
|
|
230
|
+
required: "Please enter a username",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Localization
|
|
238
|
+
|
|
239
|
+
Pass a `localize` function compatible with i18next to get localized error messages:
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import { useTranslation } from 'react-i18next';
|
|
243
|
+
|
|
244
|
+
const { t } = useTranslation();
|
|
245
|
+
const validationSchema = createValidationSchema(
|
|
246
|
+
{ schema, uiSchema },
|
|
247
|
+
{},
|
|
248
|
+
{ localize: t }
|
|
249
|
+
);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The function will be called with keys like `validation.error.minLength`, `validation.error.required`, etc.
|
|
253
|
+
|
|
254
|
+
#### Error Message Priority
|
|
255
|
+
|
|
256
|
+
1. **Custom UI message** - `uiSchema["ui:validation"].error[keyword]`
|
|
257
|
+
2. **Localized message** - Result from `localize("validation.error.{keyword}", params)`
|
|
258
|
+
3. **Default message** - Built-in English messages
|
|
259
|
+
|
|
260
|
+
#### Example
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
const schema = {
|
|
264
|
+
type: "object",
|
|
265
|
+
required: ["email", "age"],
|
|
266
|
+
properties: {
|
|
267
|
+
email: {
|
|
268
|
+
type: "string",
|
|
269
|
+
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
|
270
|
+
},
|
|
271
|
+
age: {
|
|
272
|
+
type: "number",
|
|
273
|
+
minimum: 18,
|
|
274
|
+
maximum: 120,
|
|
275
|
+
},
|
|
276
|
+
tags: {
|
|
277
|
+
type: "array",
|
|
278
|
+
minItems: 1,
|
|
279
|
+
maxItems: 5,
|
|
280
|
+
uniqueItems: true,
|
|
281
|
+
items: { type: "string" },
|
|
282
|
+
},
|
|
283
|
+
status: {
|
|
284
|
+
type: "string",
|
|
285
|
+
const: "active",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const uiSchema = {
|
|
291
|
+
email: {
|
|
292
|
+
"ui:validation": {
|
|
293
|
+
error: {
|
|
294
|
+
pattern: "Please enter a valid email address",
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const validationSchema = createValidationSchema({ schema, uiSchema });
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### Password Confirmation (Cross-Field Validation)
|
|
304
|
+
|
|
305
|
+
Use `const: { $data: "1/fieldName" }` to validate that one field equals another. The `1/` prefix uses JSON Pointer syntax to reference a sibling field (go up 1 level):
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
const schema = {
|
|
309
|
+
type: "object",
|
|
310
|
+
required: ["password", "confirmPassword"],
|
|
311
|
+
properties: {
|
|
312
|
+
password: {
|
|
313
|
+
type: "string",
|
|
314
|
+
title: "Password",
|
|
315
|
+
minLength: 8,
|
|
316
|
+
},
|
|
317
|
+
confirmPassword: {
|
|
318
|
+
type: "string",
|
|
319
|
+
title: "Confirm password",
|
|
320
|
+
const: { $data: "1/password" }, // Must match password field
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const uiSchema = {
|
|
326
|
+
confirmPassword: {
|
|
327
|
+
"ui:validation": {
|
|
328
|
+
error: {
|
|
329
|
+
const: "Passwords must match",
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const validationSchema = createValidationSchema({ schema, uiSchema });
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The `$data` reference syntax follows the AJV validation library pattern with JSON Pointer paths. This is only supported for `const` keyword at the moment, but it can be extended to support other keywords in the future (e.g. minimum to compare endDate is after startDate).
|
|
339
|
+
|
|
340
|
+
|
|
178
341
|
### Using custom components
|
|
179
342
|
|
|
180
343
|
Form components (such as wrappers) can be overridden with custom ones
|
|
@@ -1061,3 +1224,27 @@ const uiSchema: UiSchema = {
|
|
|
1061
1224
|
hideSubmit={true} // hides submit-button of the form
|
|
1062
1225
|
/>
|
|
1063
1226
|
```
|
|
1227
|
+
|
|
1228
|
+
### Special handling of conflicting keys in uiSchema
|
|
1229
|
+
|
|
1230
|
+
In case one of your property names matches a reserved key in `uiSchema` (e.g. `ui:description`), you can use the syntax `> propertyName` to target the property.
|
|
1231
|
+
|
|
1232
|
+
```tsx
|
|
1233
|
+
const schema = {
|
|
1234
|
+
type: "object",
|
|
1235
|
+
properties: {
|
|
1236
|
+
"ui:description": { type: "string", title: "Description" },
|
|
1237
|
+
},
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
const uiSchema = {
|
|
1241
|
+
// This would be interpreted as the description for the parent object
|
|
1242
|
+
"ui:description": "Form description",
|
|
1243
|
+
|
|
1244
|
+
// This targets the property named "ui:description"
|
|
1245
|
+
"> ui:description": {
|
|
1246
|
+
"ui:placeholder": "Enter description...",
|
|
1247
|
+
},
|
|
1248
|
+
};
|
|
1249
|
+
```
|
|
1250
|
+
|
|
@@ -12,7 +12,7 @@ const types_1 = require("./types");
|
|
|
12
12
|
const DEFAULT_FIELD = {
|
|
13
13
|
type: "string",
|
|
14
14
|
_fieldType: "string",
|
|
15
|
-
"ui:title": "
|
|
15
|
+
"ui:title": "",
|
|
16
16
|
};
|
|
17
17
|
const useObjectField = (name) => {
|
|
18
18
|
if (!name) {
|
|
@@ -73,7 +73,11 @@ const ObjectField = (props) => {
|
|
|
73
73
|
const childSchema = properties?.[child];
|
|
74
74
|
if (!childSchema)
|
|
75
75
|
return undefined;
|
|
76
|
-
|
|
76
|
+
const childUiSchema = {
|
|
77
|
+
...(uiSchema?.properties ?? {}),
|
|
78
|
+
...(uiSchema?.[`> ${child}`] ?? uiSchema?.[child] ?? {}),
|
|
79
|
+
};
|
|
80
|
+
return ((0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(child), name: name ? [name, child].join(".") : child, schema: prepareChildSchema(childSchema, schema), uiSchema: childUiSchema }, child));
|
|
77
81
|
}
|
|
78
82
|
else {
|
|
79
83
|
const { title, fields, collapsible } = child;
|
|
@@ -81,7 +85,13 @@ const ObjectField = (props) => {
|
|
|
81
85
|
const childSchema = properties?.[child2];
|
|
82
86
|
if (!childSchema)
|
|
83
87
|
return undefined;
|
|
84
|
-
|
|
88
|
+
const childUiSchema = {
|
|
89
|
+
...(uiSchema?.properties ?? {}),
|
|
90
|
+
...(uiSchema?.[`> ${child2}`] ??
|
|
91
|
+
uiSchema?.[child2] ??
|
|
92
|
+
{}),
|
|
93
|
+
};
|
|
94
|
+
return ((0, jsx_runtime_1.jsx)(SchemaField, { name: name ? [name, child2].join(".") : child2, schema: prepareChildSchema(childSchema, schema), uiSchema: childUiSchema }, child2));
|
|
85
95
|
}) }, fields.join("_")));
|
|
86
96
|
}
|
|
87
97
|
})
|
|
@@ -89,7 +99,10 @@ const ObjectField = (props) => {
|
|
|
89
99
|
const childSchema = properties?.[child];
|
|
90
100
|
if (!childSchema)
|
|
91
101
|
return undefined;
|
|
92
|
-
const childUiSchema =
|
|
102
|
+
const childUiSchema = {
|
|
103
|
+
...(uiSchema?.properties ?? {}),
|
|
104
|
+
...(uiSchema?.[`> ${child}`] ?? uiSchema?.[child] ?? {}),
|
|
105
|
+
};
|
|
93
106
|
return ((0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(child), name: name ? [name, child].join(".") : child, schema: prepareChildSchema(childSchema, schema), uiSchema: {
|
|
94
107
|
...childUiSchema,
|
|
95
108
|
props: {
|
|
@@ -105,12 +118,12 @@ const ObjectField = (props) => {
|
|
|
105
118
|
}, style: { display: "none" } }, child));
|
|
106
119
|
}), showAdditionalProperties &&
|
|
107
120
|
orderedAdditionalProperties.map((childName, index) => {
|
|
108
|
-
|
|
121
|
+
const childUiSchema = {
|
|
109
122
|
...(uiSchema?.additionalProperties ?? {}),
|
|
110
123
|
...(uiSchema?.properties ?? {}),
|
|
111
|
-
...(uiSchema?.[childName] ?? {}),
|
|
124
|
+
...(uiSchema?.[`> ${childName}`] ?? uiSchema?.[childName] ?? {}),
|
|
112
125
|
};
|
|
113
|
-
return ((0, jsx_runtime_1.jsxs)(ObjectFieldItem, { children: [(0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema:
|
|
126
|
+
return ((0, jsx_runtime_1.jsxs)(ObjectFieldItem, { children: [(0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: childUiSchema }, childName), (0, jsx_runtime_1.jsxs)(ObjectFieldItemButtons, { children: [onAdditionalPropertyOrderChange &&
|
|
114
127
|
index > 0 &&
|
|
115
128
|
getObjectFieldButton({
|
|
116
129
|
purpose: types_1.ObjectFieldButtonPurpose.MOVE_UP,
|
|
@@ -140,15 +153,12 @@ const ObjectField = (props) => {
|
|
|
140
153
|
})] })] }, childName));
|
|
141
154
|
}), showAdditionalProperties &&
|
|
142
155
|
hiddenAdditionalProperties.map((childName) => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
uiSchema?.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
return ((0, jsx_runtime_1.jsx)(ObjectFieldItem, { style: { display: "none" }, children: (0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: correctUiSchema }, childName) }, childName));
|
|
156
|
+
const childUiSchema = {
|
|
157
|
+
...(uiSchema?.additionalProperties ?? {}),
|
|
158
|
+
...(uiSchema?.properties ?? {}),
|
|
159
|
+
...(uiSchema?.[`> ${childName}`] ?? uiSchema?.[childName] ?? {}),
|
|
160
|
+
};
|
|
161
|
+
return ((0, jsx_runtime_1.jsx)(ObjectFieldItem, { style: { display: "none" }, children: (0, jsx_runtime_1.jsx)(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: childUiSchema }, childName) }, childName));
|
|
152
162
|
}), additionalProperties &&
|
|
153
163
|
getObjectFieldButton({
|
|
154
164
|
purpose: types_1.ObjectFieldButtonPurpose.ADD,
|
|
@@ -37,6 +37,23 @@ exports.createValidationSchema = createValidationSchema;
|
|
|
37
37
|
const Yup = __importStar(require("yup"));
|
|
38
38
|
const resolveSchema_1 = require("./resolveSchema");
|
|
39
39
|
const solveReferences_1 = require("./solveReferences");
|
|
40
|
+
const DEFAULT_ERROR_MESSAGES = {
|
|
41
|
+
required: "Required",
|
|
42
|
+
minLength: (params) => `Must be at least ${params.limit} characters`,
|
|
43
|
+
maxLength: (params) => `Must be at most ${params.limit} characters`,
|
|
44
|
+
pattern: "Invalid format",
|
|
45
|
+
minimum: (params) => `Must be at least ${params.min}`,
|
|
46
|
+
maximum: (params) => `Must be at most ${params.max}`,
|
|
47
|
+
exclusiveMinimum: (params) => `Must be more than ${params.min}`,
|
|
48
|
+
exclusiveMaximum: (params) => `Must be less than ${params.max}`,
|
|
49
|
+
multipleOf: (params) => `Must be a multiple of ${params.multipleOf}`,
|
|
50
|
+
minItems: (params) => `Must have at least ${params.min} items`,
|
|
51
|
+
maxItems: (params) => `Must have at most ${params.max} items`,
|
|
52
|
+
uniqueItems: "Items must be unique",
|
|
53
|
+
enum: "Invalid value",
|
|
54
|
+
const: "Invalid value",
|
|
55
|
+
notConst: "Invalid value",
|
|
56
|
+
};
|
|
40
57
|
// Difficult to solve
|
|
41
58
|
// @ts-expect-error
|
|
42
59
|
Yup.addMethod(Yup.array, "mixedOf", function ({ itemSchemas, additionalItemSchema }) {
|
|
@@ -48,7 +65,7 @@ Yup.addMethod(Yup.array, "mixedOf", function ({ itemSchemas, additionalItemSchem
|
|
|
48
65
|
const numOfAdditionalItems = itemSchemas.length > valueLength ? 0 : valueLength - itemSchemas.length;
|
|
49
66
|
const additionalSchemas = additionalItemSchema
|
|
50
67
|
? Array(numOfAdditionalItems).fill(additionalItemSchema)
|
|
51
|
-
:
|
|
68
|
+
: Array(numOfAdditionalItems).fill(Yup.mixed());
|
|
52
69
|
return Yup.tuple([...itemSchemas, ...additionalSchemas]).typeError("Required");
|
|
53
70
|
});
|
|
54
71
|
});
|
|
@@ -156,10 +173,22 @@ function getYupType(schema) {
|
|
|
156
173
|
throw new Error(`createValidationSchema: Unsupported schema type: ${type}`);
|
|
157
174
|
}
|
|
158
175
|
}
|
|
159
|
-
function createValidationSchema(
|
|
176
|
+
function createValidationSchema(schemas, definitions = {}, options) {
|
|
177
|
+
const { schema, uiSchema = {} } = schemas;
|
|
178
|
+
const { localize, conditionsContext = {}, condition } = options ?? {};
|
|
160
179
|
if (!schema?.properties) {
|
|
161
180
|
return Yup.object().shape({});
|
|
162
181
|
}
|
|
182
|
+
const getErrorMessage = (key, fieldUiSchema, params) => {
|
|
183
|
+
const uiError = fieldUiSchema?.["ui:validation"]?.error?.[key];
|
|
184
|
+
if (uiError)
|
|
185
|
+
return uiError;
|
|
186
|
+
if (localize) {
|
|
187
|
+
return localize(`validation.error.${key}`, params);
|
|
188
|
+
}
|
|
189
|
+
const defaultMsg = DEFAULT_ERROR_MESSAGES[key];
|
|
190
|
+
return typeof defaultMsg === "function" ? defaultMsg(params) : defaultMsg;
|
|
191
|
+
};
|
|
163
192
|
const schemaDefinitions = {
|
|
164
193
|
...definitions,
|
|
165
194
|
...(schema.definitions ?? {}),
|
|
@@ -170,8 +199,15 @@ function createValidationSchema(schema, definitions = {}, conditionsContext = {}
|
|
|
170
199
|
const isRequired = requiredFields?.includes(key) || required === true;
|
|
171
200
|
let type = schema.type;
|
|
172
201
|
let yupSchema;
|
|
202
|
+
const fieldUiSchema = uiSchema?.[key];
|
|
173
203
|
if (schema.properties) {
|
|
174
|
-
yupSchema = createValidationSchema(
|
|
204
|
+
yupSchema = createValidationSchema({
|
|
205
|
+
schema,
|
|
206
|
+
uiSchema: fieldUiSchema
|
|
207
|
+
}, schemaDefinitions, {
|
|
208
|
+
localize,
|
|
209
|
+
conditionsContext,
|
|
210
|
+
});
|
|
175
211
|
type = type ?? "object";
|
|
176
212
|
}
|
|
177
213
|
else if (type === "array" && schema.anyOf) {
|
|
@@ -186,7 +222,9 @@ function createValidationSchema(schema, definitions = {}, conditionsContext = {}
|
|
|
186
222
|
return Yup.mixed().oneOf(anyOf.map((item) => item.const));
|
|
187
223
|
}));
|
|
188
224
|
// In case the property is required, there should be at least one item in the array
|
|
189
|
-
yupSchema = isRequired
|
|
225
|
+
yupSchema = isRequired
|
|
226
|
+
? anyOfSchema.min(1, getErrorMessage("required", fieldUiSchema))
|
|
227
|
+
: anyOfSchema;
|
|
190
228
|
}
|
|
191
229
|
}
|
|
192
230
|
else if (type === "array") {
|
|
@@ -218,8 +256,99 @@ function createValidationSchema(schema, definitions = {}, conditionsContext = {}
|
|
|
218
256
|
}
|
|
219
257
|
if (type === "null")
|
|
220
258
|
yupSchema.nullable();
|
|
259
|
+
// Apply JSON Schema validation keywords based on type
|
|
260
|
+
if (type === "string") {
|
|
261
|
+
let stringSchema = yupSchema;
|
|
262
|
+
if (schema.minLength !== undefined) {
|
|
263
|
+
stringSchema = stringSchema.min(schema.minLength, getErrorMessage("minLength", fieldUiSchema, { limit: schema.minLength }));
|
|
264
|
+
}
|
|
265
|
+
if (schema.maxLength !== undefined) {
|
|
266
|
+
stringSchema = stringSchema.max(schema.maxLength, getErrorMessage("maxLength", fieldUiSchema, { limit: schema.maxLength }));
|
|
267
|
+
}
|
|
268
|
+
if (schema.pattern !== undefined) {
|
|
269
|
+
stringSchema = stringSchema.matches(new RegExp(schema.pattern), getErrorMessage("pattern", fieldUiSchema));
|
|
270
|
+
}
|
|
271
|
+
yupSchema = stringSchema;
|
|
272
|
+
}
|
|
273
|
+
if (type === "number" || type === "integer") {
|
|
274
|
+
let numberSchema = yupSchema;
|
|
275
|
+
if (schema.minimum !== undefined) {
|
|
276
|
+
numberSchema = numberSchema.min(schema.minimum, getErrorMessage("minimum", fieldUiSchema, { min: schema.minimum }));
|
|
277
|
+
}
|
|
278
|
+
if (schema.maximum !== undefined) {
|
|
279
|
+
numberSchema = numberSchema.max(schema.maximum, getErrorMessage("maximum", fieldUiSchema, { max: schema.maximum }));
|
|
280
|
+
}
|
|
281
|
+
if (schema.exclusiveMinimum !== undefined) {
|
|
282
|
+
numberSchema = numberSchema.moreThan(schema.exclusiveMinimum, getErrorMessage("exclusiveMinimum", fieldUiSchema, { min: schema.exclusiveMinimum }));
|
|
283
|
+
}
|
|
284
|
+
if (schema.exclusiveMaximum !== undefined) {
|
|
285
|
+
numberSchema = numberSchema.lessThan(schema.exclusiveMaximum, getErrorMessage("exclusiveMaximum", fieldUiSchema, { max: schema.exclusiveMaximum }));
|
|
286
|
+
}
|
|
287
|
+
if (schema.multipleOf !== undefined) {
|
|
288
|
+
numberSchema = numberSchema.test("multipleOf", getErrorMessage("multipleOf", fieldUiSchema, { multipleOf: schema.multipleOf }), (value) => value === undefined ||
|
|
289
|
+
value === null ||
|
|
290
|
+
value % schema.multipleOf === 0);
|
|
291
|
+
}
|
|
292
|
+
yupSchema = numberSchema;
|
|
293
|
+
}
|
|
294
|
+
if (type === "array") {
|
|
295
|
+
const applyArrayTests = (s) => {
|
|
296
|
+
let result = s;
|
|
297
|
+
if (schema.minItems !== undefined) {
|
|
298
|
+
result = result.test("minItems", getErrorMessage("minItems", fieldUiSchema, { min: schema.minItems }), (value) => !value || value.length >= schema.minItems);
|
|
299
|
+
}
|
|
300
|
+
if (schema.maxItems !== undefined) {
|
|
301
|
+
result = result.test("maxItems", getErrorMessage("maxItems", fieldUiSchema, { max: schema.maxItems }), (value) => !value || value.length <= schema.maxItems);
|
|
302
|
+
}
|
|
303
|
+
if (schema.uniqueItems === true) {
|
|
304
|
+
result = result.test("uniqueItems", getErrorMessage("uniqueItems", fieldUiSchema), (value) => {
|
|
305
|
+
if (!value)
|
|
306
|
+
return true;
|
|
307
|
+
return new Set(value).size === value.length;
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return result;
|
|
311
|
+
};
|
|
312
|
+
if (yupSchema.test) {
|
|
313
|
+
yupSchema = applyArrayTests(yupSchema);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// It's likely a Lazy schema (from mixedOf). Wrap it to apply tests.
|
|
317
|
+
const originalLazy = yupSchema;
|
|
318
|
+
yupSchema = Yup.lazy((value, options) => {
|
|
319
|
+
return applyArrayTests(originalLazy.resolve(options));
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const isOptionEnum = schema.enum !== undefined;
|
|
324
|
+
const isOptionConst = schema.const !== undefined;
|
|
325
|
+
if (isOptionEnum || isOptionConst) {
|
|
326
|
+
// Check for $data reference (cross-field validation)
|
|
327
|
+
const constValue = schema.const;
|
|
328
|
+
const isDataRef = typeof constValue === "object" && constValue?.$data;
|
|
329
|
+
if (isDataRef) {
|
|
330
|
+
// Cross-field reference: const: { $data: "1/otherFieldName" }
|
|
331
|
+
// JSON Pointer format: "1/fieldName" means go up 1 level and reference fieldName
|
|
332
|
+
const dataPath = constValue.$data;
|
|
333
|
+
const pathParts = dataPath.split("/");
|
|
334
|
+
const refFieldName = pathParts[pathParts.length - 1]; // Get the field name (last part)
|
|
335
|
+
yupSchema = yupSchema.oneOf([Yup.ref(refFieldName)], getErrorMessage("const", fieldUiSchema));
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// Standard const or enum validation
|
|
339
|
+
const allowedValues = isOptionConst ? [schema.const] : schema.enum;
|
|
340
|
+
const errorKey = isOptionConst ? "const" : "enum";
|
|
341
|
+
yupSchema = yupSchema.oneOf(allowedValues, getErrorMessage(errorKey, fieldUiSchema));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (schema.not &&
|
|
345
|
+
typeof schema.not !== "boolean" &&
|
|
346
|
+
schema.not.const !== undefined) {
|
|
347
|
+
yupSchema = yupSchema.notOneOf([schema.not.const], getErrorMessage("notConst", fieldUiSchema));
|
|
348
|
+
}
|
|
349
|
+
// JSON Schema validation keywords
|
|
221
350
|
if (isRequired && type !== "array") {
|
|
222
|
-
yupSchema = yupSchema.required("
|
|
351
|
+
yupSchema = yupSchema.required(getErrorMessage("required", fieldUiSchema));
|
|
223
352
|
}
|
|
224
353
|
if (!condition) {
|
|
225
354
|
return yupSchema;
|
|
@@ -257,6 +386,13 @@ function createValidationSchema(schema, definitions = {}, conditionsContext = {}
|
|
|
257
386
|
override ones in the base, including type, presence and nullability."
|
|
258
387
|
Source: https://github.com/jquense/yup?tab=readme-ov-file#schemaconcatschema-schema-schema
|
|
259
388
|
*/
|
|
260
|
-
return validationSchema.concat(createValidationSchema(
|
|
389
|
+
return validationSchema.concat(createValidationSchema({
|
|
390
|
+
schema: solvedSchemas.schema,
|
|
391
|
+
uiSchema
|
|
392
|
+
}, schemaDefinitions, {
|
|
393
|
+
localize,
|
|
394
|
+
conditionsContext,
|
|
395
|
+
condition: conditionalValidation.condition
|
|
396
|
+
}));
|
|
261
397
|
}, baseValidationSchema);
|
|
262
398
|
}
|
|
@@ -9,7 +9,7 @@ import { ObjectFieldButtonPurpose } from "./types";
|
|
|
9
9
|
const DEFAULT_FIELD = {
|
|
10
10
|
type: "string",
|
|
11
11
|
_fieldType: "string",
|
|
12
|
-
"ui:title": "
|
|
12
|
+
"ui:title": "",
|
|
13
13
|
};
|
|
14
14
|
const useObjectField = (name) => {
|
|
15
15
|
if (!name) {
|
|
@@ -70,7 +70,11 @@ export const ObjectField = (props) => {
|
|
|
70
70
|
const childSchema = properties?.[child];
|
|
71
71
|
if (!childSchema)
|
|
72
72
|
return undefined;
|
|
73
|
-
|
|
73
|
+
const childUiSchema = {
|
|
74
|
+
...(uiSchema?.properties ?? {}),
|
|
75
|
+
...(uiSchema?.[`> ${child}`] ?? uiSchema?.[child] ?? {}),
|
|
76
|
+
};
|
|
77
|
+
return (_jsx(SchemaField, { required: required?.includes(child), name: name ? [name, child].join(".") : child, schema: prepareChildSchema(childSchema, schema), uiSchema: childUiSchema }, child));
|
|
74
78
|
}
|
|
75
79
|
else {
|
|
76
80
|
const { title, fields, collapsible } = child;
|
|
@@ -78,7 +82,13 @@ export const ObjectField = (props) => {
|
|
|
78
82
|
const childSchema = properties?.[child2];
|
|
79
83
|
if (!childSchema)
|
|
80
84
|
return undefined;
|
|
81
|
-
|
|
85
|
+
const childUiSchema = {
|
|
86
|
+
...(uiSchema?.properties ?? {}),
|
|
87
|
+
...(uiSchema?.[`> ${child2}`] ??
|
|
88
|
+
uiSchema?.[child2] ??
|
|
89
|
+
{}),
|
|
90
|
+
};
|
|
91
|
+
return (_jsx(SchemaField, { name: name ? [name, child2].join(".") : child2, schema: prepareChildSchema(childSchema, schema), uiSchema: childUiSchema }, child2));
|
|
82
92
|
}) }, fields.join("_")));
|
|
83
93
|
}
|
|
84
94
|
})
|
|
@@ -86,7 +96,10 @@ export const ObjectField = (props) => {
|
|
|
86
96
|
const childSchema = properties?.[child];
|
|
87
97
|
if (!childSchema)
|
|
88
98
|
return undefined;
|
|
89
|
-
const childUiSchema =
|
|
99
|
+
const childUiSchema = {
|
|
100
|
+
...(uiSchema?.properties ?? {}),
|
|
101
|
+
...(uiSchema?.[`> ${child}`] ?? uiSchema?.[child] ?? {}),
|
|
102
|
+
};
|
|
90
103
|
return (_jsx(SchemaField, { required: required?.includes(child), name: name ? [name, child].join(".") : child, schema: prepareChildSchema(childSchema, schema), uiSchema: {
|
|
91
104
|
...childUiSchema,
|
|
92
105
|
props: {
|
|
@@ -102,12 +115,12 @@ export const ObjectField = (props) => {
|
|
|
102
115
|
}, style: { display: "none" } }, child));
|
|
103
116
|
}), showAdditionalProperties &&
|
|
104
117
|
orderedAdditionalProperties.map((childName, index) => {
|
|
105
|
-
|
|
118
|
+
const childUiSchema = {
|
|
106
119
|
...(uiSchema?.additionalProperties ?? {}),
|
|
107
120
|
...(uiSchema?.properties ?? {}),
|
|
108
|
-
...(uiSchema?.[childName] ?? {}),
|
|
121
|
+
...(uiSchema?.[`> ${childName}`] ?? uiSchema?.[childName] ?? {}),
|
|
109
122
|
};
|
|
110
|
-
return (_jsxs(ObjectFieldItem, { children: [_jsx(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema:
|
|
123
|
+
return (_jsxs(ObjectFieldItem, { children: [_jsx(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: childUiSchema }, childName), _jsxs(ObjectFieldItemButtons, { children: [onAdditionalPropertyOrderChange &&
|
|
111
124
|
index > 0 &&
|
|
112
125
|
getObjectFieldButton({
|
|
113
126
|
purpose: ObjectFieldButtonPurpose.MOVE_UP,
|
|
@@ -137,15 +150,12 @@ export const ObjectField = (props) => {
|
|
|
137
150
|
})] })] }, childName));
|
|
138
151
|
}), showAdditionalProperties &&
|
|
139
152
|
hiddenAdditionalProperties.map((childName) => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
uiSchema?.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
return (_jsx(ObjectFieldItem, { style: { display: "none" }, children: _jsx(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: correctUiSchema }, childName) }, childName));
|
|
153
|
+
const childUiSchema = {
|
|
154
|
+
...(uiSchema?.additionalProperties ?? {}),
|
|
155
|
+
...(uiSchema?.properties ?? {}),
|
|
156
|
+
...(uiSchema?.[`> ${childName}`] ?? uiSchema?.[childName] ?? {}),
|
|
157
|
+
};
|
|
158
|
+
return (_jsx(ObjectFieldItem, { style: { display: "none" }, children: _jsx(SchemaField, { required: required?.includes(childName), name: name ? [name, childName].join(".") : childName, schema: prepareChildSchema(schema.additionalProperties, schema), uiSchema: childUiSchema }, childName) }, childName));
|
|
149
159
|
}), additionalProperties &&
|
|
150
160
|
getObjectFieldButton({
|
|
151
161
|
purpose: ObjectFieldButtonPurpose.ADD,
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import * as Yup from "yup";
|
|
2
2
|
import { resolveOneOfValue } from "./resolveSchema";
|
|
3
3
|
import { solveReferences } from "./solveReferences";
|
|
4
|
+
const DEFAULT_ERROR_MESSAGES = {
|
|
5
|
+
required: "Required",
|
|
6
|
+
minLength: (params) => `Must be at least ${params.limit} characters`,
|
|
7
|
+
maxLength: (params) => `Must be at most ${params.limit} characters`,
|
|
8
|
+
pattern: "Invalid format",
|
|
9
|
+
minimum: (params) => `Must be at least ${params.min}`,
|
|
10
|
+
maximum: (params) => `Must be at most ${params.max}`,
|
|
11
|
+
exclusiveMinimum: (params) => `Must be more than ${params.min}`,
|
|
12
|
+
exclusiveMaximum: (params) => `Must be less than ${params.max}`,
|
|
13
|
+
multipleOf: (params) => `Must be a multiple of ${params.multipleOf}`,
|
|
14
|
+
minItems: (params) => `Must have at least ${params.min} items`,
|
|
15
|
+
maxItems: (params) => `Must have at most ${params.max} items`,
|
|
16
|
+
uniqueItems: "Items must be unique",
|
|
17
|
+
enum: "Invalid value",
|
|
18
|
+
const: "Invalid value",
|
|
19
|
+
notConst: "Invalid value",
|
|
20
|
+
};
|
|
4
21
|
// Difficult to solve
|
|
5
22
|
// @ts-expect-error
|
|
6
23
|
Yup.addMethod(Yup.array, "mixedOf", function ({ itemSchemas, additionalItemSchema }) {
|
|
@@ -12,7 +29,7 @@ Yup.addMethod(Yup.array, "mixedOf", function ({ itemSchemas, additionalItemSchem
|
|
|
12
29
|
const numOfAdditionalItems = itemSchemas.length > valueLength ? 0 : valueLength - itemSchemas.length;
|
|
13
30
|
const additionalSchemas = additionalItemSchema
|
|
14
31
|
? Array(numOfAdditionalItems).fill(additionalItemSchema)
|
|
15
|
-
:
|
|
32
|
+
: Array(numOfAdditionalItems).fill(Yup.mixed());
|
|
16
33
|
return Yup.tuple([...itemSchemas, ...additionalSchemas]).typeError("Required");
|
|
17
34
|
});
|
|
18
35
|
});
|
|
@@ -120,10 +137,22 @@ function getYupType(schema) {
|
|
|
120
137
|
throw new Error(`createValidationSchema: Unsupported schema type: ${type}`);
|
|
121
138
|
}
|
|
122
139
|
}
|
|
123
|
-
export function createValidationSchema(
|
|
140
|
+
export function createValidationSchema(schemas, definitions = {}, options) {
|
|
141
|
+
const { schema, uiSchema = {} } = schemas;
|
|
142
|
+
const { localize, conditionsContext = {}, condition } = options ?? {};
|
|
124
143
|
if (!schema?.properties) {
|
|
125
144
|
return Yup.object().shape({});
|
|
126
145
|
}
|
|
146
|
+
const getErrorMessage = (key, fieldUiSchema, params) => {
|
|
147
|
+
const uiError = fieldUiSchema?.["ui:validation"]?.error?.[key];
|
|
148
|
+
if (uiError)
|
|
149
|
+
return uiError;
|
|
150
|
+
if (localize) {
|
|
151
|
+
return localize(`validation.error.${key}`, params);
|
|
152
|
+
}
|
|
153
|
+
const defaultMsg = DEFAULT_ERROR_MESSAGES[key];
|
|
154
|
+
return typeof defaultMsg === "function" ? defaultMsg(params) : defaultMsg;
|
|
155
|
+
};
|
|
127
156
|
const schemaDefinitions = {
|
|
128
157
|
...definitions,
|
|
129
158
|
...(schema.definitions ?? {}),
|
|
@@ -134,8 +163,15 @@ export function createValidationSchema(schema, definitions = {}, conditionsConte
|
|
|
134
163
|
const isRequired = requiredFields?.includes(key) || required === true;
|
|
135
164
|
let type = schema.type;
|
|
136
165
|
let yupSchema;
|
|
166
|
+
const fieldUiSchema = uiSchema?.[key];
|
|
137
167
|
if (schema.properties) {
|
|
138
|
-
yupSchema = createValidationSchema(
|
|
168
|
+
yupSchema = createValidationSchema({
|
|
169
|
+
schema,
|
|
170
|
+
uiSchema: fieldUiSchema
|
|
171
|
+
}, schemaDefinitions, {
|
|
172
|
+
localize,
|
|
173
|
+
conditionsContext,
|
|
174
|
+
});
|
|
139
175
|
type = type ?? "object";
|
|
140
176
|
}
|
|
141
177
|
else if (type === "array" && schema.anyOf) {
|
|
@@ -150,7 +186,9 @@ export function createValidationSchema(schema, definitions = {}, conditionsConte
|
|
|
150
186
|
return Yup.mixed().oneOf(anyOf.map((item) => item.const));
|
|
151
187
|
}));
|
|
152
188
|
// In case the property is required, there should be at least one item in the array
|
|
153
|
-
yupSchema = isRequired
|
|
189
|
+
yupSchema = isRequired
|
|
190
|
+
? anyOfSchema.min(1, getErrorMessage("required", fieldUiSchema))
|
|
191
|
+
: anyOfSchema;
|
|
154
192
|
}
|
|
155
193
|
}
|
|
156
194
|
else if (type === "array") {
|
|
@@ -182,8 +220,99 @@ export function createValidationSchema(schema, definitions = {}, conditionsConte
|
|
|
182
220
|
}
|
|
183
221
|
if (type === "null")
|
|
184
222
|
yupSchema.nullable();
|
|
223
|
+
// Apply JSON Schema validation keywords based on type
|
|
224
|
+
if (type === "string") {
|
|
225
|
+
let stringSchema = yupSchema;
|
|
226
|
+
if (schema.minLength !== undefined) {
|
|
227
|
+
stringSchema = stringSchema.min(schema.minLength, getErrorMessage("minLength", fieldUiSchema, { limit: schema.minLength }));
|
|
228
|
+
}
|
|
229
|
+
if (schema.maxLength !== undefined) {
|
|
230
|
+
stringSchema = stringSchema.max(schema.maxLength, getErrorMessage("maxLength", fieldUiSchema, { limit: schema.maxLength }));
|
|
231
|
+
}
|
|
232
|
+
if (schema.pattern !== undefined) {
|
|
233
|
+
stringSchema = stringSchema.matches(new RegExp(schema.pattern), getErrorMessage("pattern", fieldUiSchema));
|
|
234
|
+
}
|
|
235
|
+
yupSchema = stringSchema;
|
|
236
|
+
}
|
|
237
|
+
if (type === "number" || type === "integer") {
|
|
238
|
+
let numberSchema = yupSchema;
|
|
239
|
+
if (schema.minimum !== undefined) {
|
|
240
|
+
numberSchema = numberSchema.min(schema.minimum, getErrorMessage("minimum", fieldUiSchema, { min: schema.minimum }));
|
|
241
|
+
}
|
|
242
|
+
if (schema.maximum !== undefined) {
|
|
243
|
+
numberSchema = numberSchema.max(schema.maximum, getErrorMessage("maximum", fieldUiSchema, { max: schema.maximum }));
|
|
244
|
+
}
|
|
245
|
+
if (schema.exclusiveMinimum !== undefined) {
|
|
246
|
+
numberSchema = numberSchema.moreThan(schema.exclusiveMinimum, getErrorMessage("exclusiveMinimum", fieldUiSchema, { min: schema.exclusiveMinimum }));
|
|
247
|
+
}
|
|
248
|
+
if (schema.exclusiveMaximum !== undefined) {
|
|
249
|
+
numberSchema = numberSchema.lessThan(schema.exclusiveMaximum, getErrorMessage("exclusiveMaximum", fieldUiSchema, { max: schema.exclusiveMaximum }));
|
|
250
|
+
}
|
|
251
|
+
if (schema.multipleOf !== undefined) {
|
|
252
|
+
numberSchema = numberSchema.test("multipleOf", getErrorMessage("multipleOf", fieldUiSchema, { multipleOf: schema.multipleOf }), (value) => value === undefined ||
|
|
253
|
+
value === null ||
|
|
254
|
+
value % schema.multipleOf === 0);
|
|
255
|
+
}
|
|
256
|
+
yupSchema = numberSchema;
|
|
257
|
+
}
|
|
258
|
+
if (type === "array") {
|
|
259
|
+
const applyArrayTests = (s) => {
|
|
260
|
+
let result = s;
|
|
261
|
+
if (schema.minItems !== undefined) {
|
|
262
|
+
result = result.test("minItems", getErrorMessage("minItems", fieldUiSchema, { min: schema.minItems }), (value) => !value || value.length >= schema.minItems);
|
|
263
|
+
}
|
|
264
|
+
if (schema.maxItems !== undefined) {
|
|
265
|
+
result = result.test("maxItems", getErrorMessage("maxItems", fieldUiSchema, { max: schema.maxItems }), (value) => !value || value.length <= schema.maxItems);
|
|
266
|
+
}
|
|
267
|
+
if (schema.uniqueItems === true) {
|
|
268
|
+
result = result.test("uniqueItems", getErrorMessage("uniqueItems", fieldUiSchema), (value) => {
|
|
269
|
+
if (!value)
|
|
270
|
+
return true;
|
|
271
|
+
return new Set(value).size === value.length;
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return result;
|
|
275
|
+
};
|
|
276
|
+
if (yupSchema.test) {
|
|
277
|
+
yupSchema = applyArrayTests(yupSchema);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
// It's likely a Lazy schema (from mixedOf). Wrap it to apply tests.
|
|
281
|
+
const originalLazy = yupSchema;
|
|
282
|
+
yupSchema = Yup.lazy((value, options) => {
|
|
283
|
+
return applyArrayTests(originalLazy.resolve(options));
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const isOptionEnum = schema.enum !== undefined;
|
|
288
|
+
const isOptionConst = schema.const !== undefined;
|
|
289
|
+
if (isOptionEnum || isOptionConst) {
|
|
290
|
+
// Check for $data reference (cross-field validation)
|
|
291
|
+
const constValue = schema.const;
|
|
292
|
+
const isDataRef = typeof constValue === "object" && constValue?.$data;
|
|
293
|
+
if (isDataRef) {
|
|
294
|
+
// Cross-field reference: const: { $data: "1/otherFieldName" }
|
|
295
|
+
// JSON Pointer format: "1/fieldName" means go up 1 level and reference fieldName
|
|
296
|
+
const dataPath = constValue.$data;
|
|
297
|
+
const pathParts = dataPath.split("/");
|
|
298
|
+
const refFieldName = pathParts[pathParts.length - 1]; // Get the field name (last part)
|
|
299
|
+
yupSchema = yupSchema.oneOf([Yup.ref(refFieldName)], getErrorMessage("const", fieldUiSchema));
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// Standard const or enum validation
|
|
303
|
+
const allowedValues = isOptionConst ? [schema.const] : schema.enum;
|
|
304
|
+
const errorKey = isOptionConst ? "const" : "enum";
|
|
305
|
+
yupSchema = yupSchema.oneOf(allowedValues, getErrorMessage(errorKey, fieldUiSchema));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (schema.not &&
|
|
309
|
+
typeof schema.not !== "boolean" &&
|
|
310
|
+
schema.not.const !== undefined) {
|
|
311
|
+
yupSchema = yupSchema.notOneOf([schema.not.const], getErrorMessage("notConst", fieldUiSchema));
|
|
312
|
+
}
|
|
313
|
+
// JSON Schema validation keywords
|
|
185
314
|
if (isRequired && type !== "array") {
|
|
186
|
-
yupSchema = yupSchema.required("
|
|
315
|
+
yupSchema = yupSchema.required(getErrorMessage("required", fieldUiSchema));
|
|
187
316
|
}
|
|
188
317
|
if (!condition) {
|
|
189
318
|
return yupSchema;
|
|
@@ -221,6 +350,13 @@ export function createValidationSchema(schema, definitions = {}, conditionsConte
|
|
|
221
350
|
override ones in the base, including type, presence and nullability."
|
|
222
351
|
Source: https://github.com/jquense/yup?tab=readme-ov-file#schemaconcatschema-schema-schema
|
|
223
352
|
*/
|
|
224
|
-
return validationSchema.concat(createValidationSchema(
|
|
353
|
+
return validationSchema.concat(createValidationSchema({
|
|
354
|
+
schema: solvedSchemas.schema,
|
|
355
|
+
uiSchema
|
|
356
|
+
}, schemaDefinitions, {
|
|
357
|
+
localize,
|
|
358
|
+
conditionsContext,
|
|
359
|
+
condition: conditionalValidation.condition
|
|
360
|
+
}));
|
|
225
361
|
}, baseValidationSchema);
|
|
226
362
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as Yup from "yup";
|
|
2
2
|
import { Schema } from "../common/types";
|
|
3
|
+
import { UiSchema } from "../common/types";
|
|
4
|
+
export type LocalizeType = (key: string, params?: Record<string, any>) => string;
|
|
3
5
|
type Condition = {
|
|
4
6
|
dependentKeys: string[];
|
|
5
7
|
conditionFn: (...value: any[]) => boolean;
|
|
@@ -17,5 +19,12 @@ type ConditionsContext = {
|
|
|
17
19
|
condition: Condition;
|
|
18
20
|
yupSchema: Yup.Schema<any, any, any, "">;
|
|
19
21
|
};
|
|
20
|
-
export declare function createValidationSchema(
|
|
22
|
+
export declare function createValidationSchema(schemas: {
|
|
23
|
+
schema: Schema;
|
|
24
|
+
uiSchema?: UiSchema;
|
|
25
|
+
}, definitions?: Schema, options?: {
|
|
26
|
+
localize?: LocalizeType;
|
|
27
|
+
conditionsContext?: Record<string, ConditionsContext[]>;
|
|
28
|
+
condition?: Condition;
|
|
29
|
+
}): Yup.ObjectSchema<{}, Yup.AnyObject, {}, "">;
|
|
21
30
|
export {};
|