@rjsf/utils 5.22.3 → 5.23.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/dist/index.js +175 -59
- package/dist/index.js.map +2 -2
- package/dist/utils.esm.js +175 -59
- package/dist/utils.esm.js.map +2 -2
- package/dist/utils.umd.js +187 -63
- package/lib/ErrorSchemaBuilder.js +3 -3
- package/lib/ErrorSchemaBuilder.js.map +1 -1
- package/lib/createSchemaUtils.js +7 -7
- package/lib/createSchemaUtils.js.map +1 -1
- package/lib/schema/getClosestMatchingOption.d.ts +5 -3
- package/lib/schema/getClosestMatchingOption.js +11 -7
- package/lib/schema/getClosestMatchingOption.js.map +1 -1
- package/lib/schema/getDefaultFormState.d.ts +1 -1
- package/lib/schema/getDefaultFormState.js +40 -16
- package/lib/schema/getDefaultFormState.js.map +1 -1
- package/lib/schema/getDisplayLabel.d.ts +3 -2
- package/lib/schema/getDisplayLabel.js +4 -3
- package/lib/schema/getDisplayLabel.js.map +1 -1
- package/lib/schema/isFilesArray.d.ts +3 -2
- package/lib/schema/isFilesArray.js +3 -2
- package/lib/schema/isFilesArray.js.map +1 -1
- package/lib/schema/isMultiSelect.d.ts +3 -2
- package/lib/schema/isMultiSelect.js +3 -2
- package/lib/schema/isMultiSelect.js.map +1 -1
- package/lib/schema/isSelect.d.ts +3 -2
- package/lib/schema/isSelect.js +3 -2
- package/lib/schema/isSelect.js.map +1 -1
- package/lib/schema/retrieveSchema.d.ts +2 -1
- package/lib/schema/retrieveSchema.js +5 -4
- package/lib/schema/retrieveSchema.js.map +1 -1
- package/lib/schema/sanitizeDataForNewSchema.d.ts +3 -2
- package/lib/schema/sanitizeDataForNewSchema.js +8 -7
- package/lib/schema/sanitizeDataForNewSchema.js.map +1 -1
- package/lib/schema/toIdSchema.js +1 -1
- package/lib/schema/toIdSchema.js.map +1 -1
- package/lib/schema/toPathSchema.d.ts +3 -2
- package/lib/schema/toPathSchema.js +13 -11
- package/lib/schema/toPathSchema.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.d.ts +12 -0
- package/package.json +2 -2
- package/src/ErrorSchemaBuilder.ts +3 -3
- package/src/createSchemaUtils.ts +29 -7
- package/src/schema/getClosestMatchingOption.ts +31 -8
- package/src/schema/getDefaultFormState.ts +48 -15
- package/src/schema/getDisplayLabel.ts +6 -3
- package/src/schema/isFilesArray.ts +18 -3
- package/src/schema/isMultiSelect.ts +9 -3
- package/src/schema/isSelect.ts +5 -3
- package/src/schema/retrieveSchema.ts +19 -4
- package/src/schema/sanitizeDataForNewSchema.ts +49 -8
- package/src/schema/toIdSchema.ts +1 -1
- package/src/schema/toPathSchema.ts +45 -12
- package/src/types.ts +12 -0
|
@@ -10,7 +10,7 @@ import getFirstMatchingOption from './getFirstMatchingOption';
|
|
|
10
10
|
import retrieveSchema, { resolveAllReferences } from './retrieveSchema';
|
|
11
11
|
import { ONE_OF_KEY, REF_KEY, JUNK_OPTION_ID, ANY_OF_KEY } from '../constants';
|
|
12
12
|
import guessType from '../guessType';
|
|
13
|
-
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType } from '../types';
|
|
13
|
+
import { Experimental_CustomMergeAllOf, FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType } from '../types';
|
|
14
14
|
import getDiscriminatorFieldFromSchema from '../getDiscriminatorFieldFromSchema';
|
|
15
15
|
import getOptionMatchingSimpleDiscriminator from '../getOptionMatchingSimpleDiscriminator';
|
|
16
16
|
|
|
@@ -45,13 +45,15 @@ export const JUNK_OPTION: StrictRJSFSchema = {
|
|
|
45
45
|
* @param rootSchema - The root JSON schema of the entire form
|
|
46
46
|
* @param schema - The schema for which the score is being calculated
|
|
47
47
|
* @param formData - The form data associated with the schema, used to calculate the score
|
|
48
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
48
49
|
* @returns - The score a schema against the formData
|
|
49
50
|
*/
|
|
50
51
|
export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
51
52
|
validator: ValidatorType<T, S, F>,
|
|
52
53
|
rootSchema: S,
|
|
53
54
|
schema?: S,
|
|
54
|
-
formData?: any
|
|
55
|
+
formData?: any,
|
|
56
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
55
57
|
): number {
|
|
56
58
|
let totalScore = 0;
|
|
57
59
|
if (schema) {
|
|
@@ -64,8 +66,23 @@ export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
64
66
|
return score;
|
|
65
67
|
}
|
|
66
68
|
if (has(value, REF_KEY)) {
|
|
67
|
-
const newSchema = retrieveSchema<T, S, F>(
|
|
68
|
-
|
|
69
|
+
const newSchema = retrieveSchema<T, S, F>(
|
|
70
|
+
validator,
|
|
71
|
+
value as S,
|
|
72
|
+
rootSchema,
|
|
73
|
+
formValue,
|
|
74
|
+
experimental_customMergeAllOf
|
|
75
|
+
);
|
|
76
|
+
return (
|
|
77
|
+
score +
|
|
78
|
+
calculateIndexScore<T, S, F>(
|
|
79
|
+
validator,
|
|
80
|
+
rootSchema,
|
|
81
|
+
newSchema,
|
|
82
|
+
formValue || {},
|
|
83
|
+
experimental_customMergeAllOf
|
|
84
|
+
)
|
|
85
|
+
);
|
|
69
86
|
}
|
|
70
87
|
if ((has(value, ONE_OF_KEY) || has(value, ANY_OF_KEY)) && formValue) {
|
|
71
88
|
const key = has(value, ONE_OF_KEY) ? ONE_OF_KEY : ANY_OF_KEY;
|
|
@@ -78,7 +95,8 @@ export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
78
95
|
formValue,
|
|
79
96
|
get(value, key) as S[],
|
|
80
97
|
-1,
|
|
81
|
-
discriminator
|
|
98
|
+
discriminator,
|
|
99
|
+
experimental_customMergeAllOf
|
|
82
100
|
)
|
|
83
101
|
);
|
|
84
102
|
}
|
|
@@ -87,7 +105,10 @@ export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
87
105
|
// If the structure is matching then give it a little boost in score
|
|
88
106
|
score += 1;
|
|
89
107
|
}
|
|
90
|
-
return
|
|
108
|
+
return (
|
|
109
|
+
score +
|
|
110
|
+
calculateIndexScore<T, S, F>(validator, rootSchema, value as S, formValue, experimental_customMergeAllOf)
|
|
111
|
+
);
|
|
91
112
|
}
|
|
92
113
|
if (value.type === guessType(formValue)) {
|
|
93
114
|
// If the types match, then we bump the score by one
|
|
@@ -135,6 +156,7 @@ export function calculateIndexScore<T = any, S extends StrictRJSFSchema = RJSFSc
|
|
|
135
156
|
* @param [selectedOption=-1] - The index of the currently selected option, defaulted to -1 if not specified
|
|
136
157
|
* @param [discriminatorField] - The optional name of the field within the options object whose value is used to
|
|
137
158
|
* determine which option is selected
|
|
159
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
138
160
|
* @returns - The index of the option that is the closest match to the `formData` or the `selectedOption` if no match
|
|
139
161
|
*/
|
|
140
162
|
export default function getClosestMatchingOption<
|
|
@@ -147,7 +169,8 @@ export default function getClosestMatchingOption<
|
|
|
147
169
|
formData: T | undefined,
|
|
148
170
|
options: S[],
|
|
149
171
|
selectedOption = -1,
|
|
150
|
-
discriminatorField?: string
|
|
172
|
+
discriminatorField?: string,
|
|
173
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
151
174
|
): number {
|
|
152
175
|
// First resolve any refs in the options
|
|
153
176
|
const resolvedOptions = options.map((option) => {
|
|
@@ -185,7 +208,7 @@ export default function getClosestMatchingOption<
|
|
|
185
208
|
(scoreData: BestType, index: number) => {
|
|
186
209
|
const { bestScore } = scoreData;
|
|
187
210
|
const option = resolvedOptions[index];
|
|
188
|
-
const score = calculateIndexScore(validator, rootSchema, option, formData);
|
|
211
|
+
const score = calculateIndexScore(validator, rootSchema, option, formData, experimental_customMergeAllOf);
|
|
189
212
|
scoreCount.add(score);
|
|
190
213
|
if (score > bestScore) {
|
|
191
214
|
return { bestIndex: index, bestScore: score };
|
|
@@ -31,9 +31,10 @@ import {
|
|
|
31
31
|
} from '../types';
|
|
32
32
|
import isMultiSelect from './isMultiSelect';
|
|
33
33
|
import retrieveSchema, { resolveDependencies } from './retrieveSchema';
|
|
34
|
-
import isConstant from '../isConstant';
|
|
35
34
|
import { JSONSchema7Object } from 'json-schema';
|
|
36
35
|
|
|
36
|
+
const PRIMITIVE_TYPES = ['string', 'number', 'integer', 'boolean', 'null'];
|
|
37
|
+
|
|
37
38
|
/** Enum that indicates how `schema.additionalItems` should be handled by the `getInnerSchemaForArrayItem()` function.
|
|
38
39
|
*/
|
|
39
40
|
export enum AdditionalItemsHandling {
|
|
@@ -199,9 +200,10 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
199
200
|
let defaults: T | T[] | undefined = parentDefaults;
|
|
200
201
|
// If we get a new schema, then we need to recompute defaults again for the new schema found.
|
|
201
202
|
let schemaToCompute: S | null = null;
|
|
203
|
+
let experimental_dfsb_to_compute = experimental_defaultFormStateBehavior;
|
|
202
204
|
let updatedRecurseList = _recurseList;
|
|
203
205
|
|
|
204
|
-
if (
|
|
206
|
+
if (schema[CONST_KEY] && experimental_defaultFormStateBehavior?.constAsDefaults !== 'never') {
|
|
205
207
|
defaults = schema.const as unknown as T;
|
|
206
208
|
} else if (isObject(defaults) && isObject(schema.default)) {
|
|
207
209
|
// For object defaults, only override parent defaults that are defined in
|
|
@@ -239,6 +241,7 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
239
241
|
includeUndefinedValues,
|
|
240
242
|
_recurseList,
|
|
241
243
|
experimental_defaultFormStateBehavior,
|
|
244
|
+
experimental_customMergeAllOf,
|
|
242
245
|
parentDefaults: Array.isArray(parentDefaults) ? parentDefaults[idx] : undefined,
|
|
243
246
|
rawFormData: formData as T,
|
|
244
247
|
required,
|
|
@@ -250,6 +253,15 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
250
253
|
return undefined;
|
|
251
254
|
}
|
|
252
255
|
const discriminator = getDiscriminatorFieldFromSchema<S>(schema);
|
|
256
|
+
const { type = 'null' } = remaining;
|
|
257
|
+
if (
|
|
258
|
+
!Array.isArray(type) &&
|
|
259
|
+
PRIMITIVE_TYPES.includes(type) &&
|
|
260
|
+
experimental_dfsb_to_compute?.constAsDefaults === 'skipOneOf'
|
|
261
|
+
) {
|
|
262
|
+
// If we are in a oneOf of a primitive type, then we want to pass constAsDefaults as 'never' for the recursion
|
|
263
|
+
experimental_dfsb_to_compute = { ...experimental_dfsb_to_compute, constAsDefaults: 'never' };
|
|
264
|
+
}
|
|
253
265
|
schemaToCompute = oneOf![
|
|
254
266
|
getClosestMatchingOption<T, S, F>(
|
|
255
267
|
validator,
|
|
@@ -257,7 +269,8 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
257
269
|
isEmpty(formData) ? undefined : formData,
|
|
258
270
|
oneOf as S[],
|
|
259
271
|
0,
|
|
260
|
-
discriminator
|
|
272
|
+
discriminator,
|
|
273
|
+
experimental_customMergeAllOf
|
|
261
274
|
)
|
|
262
275
|
] as S;
|
|
263
276
|
schemaToCompute = mergeSchemas(remaining, schemaToCompute) as S;
|
|
@@ -274,7 +287,8 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
274
287
|
isEmpty(formData) ? undefined : formData,
|
|
275
288
|
anyOf as S[],
|
|
276
289
|
0,
|
|
277
|
-
discriminator
|
|
290
|
+
discriminator,
|
|
291
|
+
experimental_customMergeAllOf
|
|
278
292
|
)
|
|
279
293
|
] as S;
|
|
280
294
|
schemaToCompute = mergeSchemas(remaining, schemaToCompute) as S;
|
|
@@ -285,7 +299,8 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
|
|
|
285
299
|
rootSchema,
|
|
286
300
|
includeUndefinedValues,
|
|
287
301
|
_recurseList: updatedRecurseList,
|
|
288
|
-
experimental_defaultFormStateBehavior,
|
|
302
|
+
experimental_defaultFormStateBehavior: experimental_dfsb_to_compute,
|
|
303
|
+
experimental_customMergeAllOf,
|
|
289
304
|
parentDefaults: defaults as T | undefined,
|
|
290
305
|
rawFormData: formData as T,
|
|
291
306
|
required,
|
|
@@ -337,9 +352,12 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
337
352
|
const objectDefaults = Object.keys(retrievedSchema.properties || {}).reduce(
|
|
338
353
|
(acc: GenericObjectType, key: string) => {
|
|
339
354
|
const propertySchema = get(retrievedSchema, [PROPERTIES_KEY, key]);
|
|
340
|
-
// Check if the parent schema has a const property defined
|
|
355
|
+
// Check if the parent schema has a const property defined AND we are supporting const as defaults, then we
|
|
356
|
+
// should always return the computedDefault since it's coming from the const.
|
|
341
357
|
const hasParentConst = isObject(parentConst) && (parentConst as JSONSchema7Object)[key] !== undefined;
|
|
342
|
-
const hasConst =
|
|
358
|
+
const hasConst =
|
|
359
|
+
((isObject(propertySchema) && CONST_KEY in propertySchema) || hasParentConst) &&
|
|
360
|
+
experimental_defaultFormStateBehavior?.constAsDefaults !== 'never';
|
|
343
361
|
// Compute the defaults for this node, with the parent defaults we might
|
|
344
362
|
// have from a previous run: defaults[key].
|
|
345
363
|
const computedDefault = computeDefaults<T, S, F>(validator, propertySchema, {
|
|
@@ -390,6 +408,7 @@ export function getObjectDefaults<T = any, S extends StrictRJSFSchema = RJSFSche
|
|
|
390
408
|
rootSchema,
|
|
391
409
|
_recurseList,
|
|
392
410
|
experimental_defaultFormStateBehavior,
|
|
411
|
+
experimental_customMergeAllOf,
|
|
393
412
|
includeUndefinedValues: includeUndefinedValues === true,
|
|
394
413
|
parentDefaults: get(defaults, [key]),
|
|
395
414
|
rawFormData: get(formData, [key]),
|
|
@@ -426,17 +445,21 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
426
445
|
rootSchema = {} as S,
|
|
427
446
|
_recurseList = [],
|
|
428
447
|
experimental_defaultFormStateBehavior = undefined,
|
|
448
|
+
experimental_customMergeAllOf = undefined,
|
|
429
449
|
required,
|
|
430
450
|
}: ComputeDefaultsProps<T, S> = {},
|
|
431
451
|
defaults?: T | T[] | undefined
|
|
432
452
|
): T | T[] | undefined {
|
|
433
453
|
const schema: S = rawSchema;
|
|
434
454
|
|
|
435
|
-
const
|
|
436
|
-
const
|
|
455
|
+
const arrayMinItemsStateBehavior = experimental_defaultFormStateBehavior?.arrayMinItems ?? {};
|
|
456
|
+
const { populate: arrayMinItemsPopulate, mergeExtraDefaults: arrayMergeExtraDefaults } = arrayMinItemsStateBehavior;
|
|
457
|
+
|
|
458
|
+
const neverPopulate = arrayMinItemsPopulate === 'never';
|
|
459
|
+
const ignoreMinItemsFlagSet = arrayMinItemsPopulate === 'requiredOnly';
|
|
460
|
+
const isPopulateAll = arrayMinItemsPopulate === 'all' || (!neverPopulate && !ignoreMinItemsFlagSet);
|
|
461
|
+
const computeSkipPopulate = arrayMinItemsStateBehavior?.computeSkipPopulate ?? (() => false);
|
|
437
462
|
const isSkipEmptyDefaults = experimental_defaultFormStateBehavior?.emptyObjectFields === 'skipEmptyDefaults';
|
|
438
|
-
const computeSkipPopulate =
|
|
439
|
-
experimental_defaultFormStateBehavior?.arrayMinItems?.computeSkipPopulate ?? (() => false);
|
|
440
463
|
|
|
441
464
|
const emptyDefault = isSkipEmptyDefaults ? undefined : [];
|
|
442
465
|
|
|
@@ -448,6 +471,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
448
471
|
rootSchema,
|
|
449
472
|
_recurseList,
|
|
450
473
|
experimental_defaultFormStateBehavior,
|
|
474
|
+
experimental_customMergeAllOf,
|
|
451
475
|
parentDefaults: item,
|
|
452
476
|
required,
|
|
453
477
|
});
|
|
@@ -460,21 +484,29 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
460
484
|
if (neverPopulate) {
|
|
461
485
|
defaults = rawFormData;
|
|
462
486
|
} else {
|
|
463
|
-
|
|
487
|
+
const itemDefaults = rawFormData.map((item: T, idx: number) => {
|
|
464
488
|
return computeDefaults<T, S, F>(validator, schemaItem, {
|
|
465
489
|
rootSchema,
|
|
466
490
|
_recurseList,
|
|
467
491
|
experimental_defaultFormStateBehavior,
|
|
492
|
+
experimental_customMergeAllOf,
|
|
468
493
|
rawFormData: item,
|
|
469
494
|
parentDefaults: get(defaults, [idx]),
|
|
470
495
|
required,
|
|
471
496
|
});
|
|
472
497
|
}) as T[];
|
|
498
|
+
|
|
499
|
+
// If the populate 'requiredOnly' flag is set then we only merge and include extra defaults if they are required.
|
|
500
|
+
// Or if populate 'all' is set we merge and include extra defaults.
|
|
501
|
+
const mergeExtraDefaults = ((ignoreMinItemsFlagSet && required) || isPopulateAll) && arrayMergeExtraDefaults;
|
|
502
|
+
defaults = mergeDefaultsWithFormData(defaults, itemDefaults, mergeExtraDefaults);
|
|
473
503
|
}
|
|
474
504
|
}
|
|
475
505
|
|
|
476
|
-
// Check if the schema has a const property defined
|
|
477
|
-
|
|
506
|
+
// Check if the schema has a const property defined AND we are supporting const as defaults, then we should always
|
|
507
|
+
// return the computedDefault since it's coming from the const.
|
|
508
|
+
const hasConst =
|
|
509
|
+
isObject(schema) && CONST_KEY in schema && experimental_defaultFormStateBehavior?.constAsDefaults !== 'never';
|
|
478
510
|
if (hasConst === false) {
|
|
479
511
|
if (neverPopulate) {
|
|
480
512
|
return defaults ?? emptyDefault;
|
|
@@ -489,7 +521,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
489
521
|
const defaultsLength = Array.isArray(defaults) ? defaults.length : 0;
|
|
490
522
|
if (
|
|
491
523
|
!schema.minItems ||
|
|
492
|
-
isMultiSelect<T, S, F>(validator, schema, rootSchema) ||
|
|
524
|
+
isMultiSelect<T, S, F>(validator, schema, rootSchema, experimental_customMergeAllOf) ||
|
|
493
525
|
computeSkipPopulate<T, S, F>(validator, schema, rootSchema) ||
|
|
494
526
|
schema.minItems <= defaultsLength
|
|
495
527
|
) {
|
|
@@ -507,6 +539,7 @@ export function getArrayDefaults<T = any, S extends StrictRJSFSchema = RJSFSchem
|
|
|
507
539
|
rootSchema,
|
|
508
540
|
_recurseList,
|
|
509
541
|
experimental_defaultFormStateBehavior,
|
|
542
|
+
experimental_customMergeAllOf,
|
|
510
543
|
required,
|
|
511
544
|
})
|
|
512
545
|
) as T[];
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
StrictRJSFSchema,
|
|
10
10
|
UiSchema,
|
|
11
11
|
ValidatorType,
|
|
12
|
+
Experimental_CustomMergeAllOf,
|
|
12
13
|
} from '../types';
|
|
13
14
|
import isFilesArray from './isFilesArray';
|
|
14
15
|
import isMultiSelect from './isMultiSelect';
|
|
@@ -21,6 +22,7 @@ import isMultiSelect from './isMultiSelect';
|
|
|
21
22
|
* @param [uiSchema={}] - The UI schema from which to derive potentially displayable information
|
|
22
23
|
* @param [rootSchema] - The root schema, used to primarily to look up `$ref`s
|
|
23
24
|
* @param [globalOptions={}] - The optional Global UI Schema from which to get any fallback `xxx` options
|
|
25
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
24
26
|
* @returns - True if the label should be displayed or false if it should not
|
|
25
27
|
*/
|
|
26
28
|
export default function getDisplayLabel<
|
|
@@ -32,7 +34,8 @@ export default function getDisplayLabel<
|
|
|
32
34
|
schema: S,
|
|
33
35
|
uiSchema: UiSchema<T, S, F> = {},
|
|
34
36
|
rootSchema?: S,
|
|
35
|
-
globalOptions?: GlobalUISchemaOptions
|
|
37
|
+
globalOptions?: GlobalUISchemaOptions,
|
|
38
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
36
39
|
): boolean {
|
|
37
40
|
const uiOptions = getUiOptions<T, S, F>(uiSchema, globalOptions);
|
|
38
41
|
const { label = true } = uiOptions;
|
|
@@ -41,8 +44,8 @@ export default function getDisplayLabel<
|
|
|
41
44
|
|
|
42
45
|
if (schemaType === 'array') {
|
|
43
46
|
displayLabel =
|
|
44
|
-
isMultiSelect<T, S, F>(validator, schema, rootSchema) ||
|
|
45
|
-
isFilesArray<T, S, F>(validator, schema, uiSchema, rootSchema) ||
|
|
47
|
+
isMultiSelect<T, S, F>(validator, schema, rootSchema, experimental_customMergeAllOf) ||
|
|
48
|
+
isFilesArray<T, S, F>(validator, schema, uiSchema, rootSchema, experimental_customMergeAllOf) ||
|
|
46
49
|
isCustomWidget(uiSchema);
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { UI_WIDGET_KEY } from '../constants';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Experimental_CustomMergeAllOf,
|
|
4
|
+
FormContextType,
|
|
5
|
+
RJSFSchema,
|
|
6
|
+
StrictRJSFSchema,
|
|
7
|
+
UiSchema,
|
|
8
|
+
ValidatorType,
|
|
9
|
+
} from '../types';
|
|
3
10
|
import retrieveSchema from './retrieveSchema';
|
|
4
11
|
|
|
5
12
|
/** Checks to see if the `schema` and `uiSchema` combination represents an array of files
|
|
@@ -8,19 +15,27 @@ import retrieveSchema from './retrieveSchema';
|
|
|
8
15
|
* @param schema - The schema for which check for array of files flag is desired
|
|
9
16
|
* @param [uiSchema={}] - The UI schema from which to check the widget
|
|
10
17
|
* @param [rootSchema] - The root schema, used to primarily to look up `$ref`s
|
|
18
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
11
19
|
* @returns - True if schema/uiSchema contains an array of files, otherwise false
|
|
12
20
|
*/
|
|
13
21
|
export default function isFilesArray<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
14
22
|
validator: ValidatorType<T, S, F>,
|
|
15
23
|
schema: S,
|
|
16
24
|
uiSchema: UiSchema<T, S, F> = {},
|
|
17
|
-
rootSchema?: S
|
|
25
|
+
rootSchema?: S,
|
|
26
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
18
27
|
) {
|
|
19
28
|
if (uiSchema[UI_WIDGET_KEY] === 'files') {
|
|
20
29
|
return true;
|
|
21
30
|
}
|
|
22
31
|
if (schema.items) {
|
|
23
|
-
const itemsSchema = retrieveSchema<T, S, F>(
|
|
32
|
+
const itemsSchema = retrieveSchema<T, S, F>(
|
|
33
|
+
validator,
|
|
34
|
+
schema.items as S,
|
|
35
|
+
rootSchema,
|
|
36
|
+
undefined,
|
|
37
|
+
experimental_customMergeAllOf
|
|
38
|
+
);
|
|
24
39
|
return itemsSchema.type === 'string' && itemsSchema.format === 'data-url';
|
|
25
40
|
}
|
|
26
41
|
return false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType } from '../types';
|
|
1
|
+
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType, Experimental_CustomMergeAllOf } from '../types';
|
|
2
2
|
|
|
3
3
|
import isSelect from './isSelect';
|
|
4
4
|
|
|
@@ -7,15 +7,21 @@ import isSelect from './isSelect';
|
|
|
7
7
|
* @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
|
|
8
8
|
* @param schema - The schema for which check for a multi-select flag is desired
|
|
9
9
|
* @param [rootSchema] - The root schema, used to primarily to look up `$ref`s
|
|
10
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
10
11
|
* @returns - True if schema contains a multi-select, otherwise false
|
|
11
12
|
*/
|
|
12
13
|
export default function isMultiSelect<
|
|
13
14
|
T = any,
|
|
14
15
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
15
16
|
F extends FormContextType = any
|
|
16
|
-
>(
|
|
17
|
+
>(
|
|
18
|
+
validator: ValidatorType<T, S, F>,
|
|
19
|
+
schema: S,
|
|
20
|
+
rootSchema?: S,
|
|
21
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
22
|
+
) {
|
|
17
23
|
if (!schema.uniqueItems || !schema.items || typeof schema.items === 'boolean') {
|
|
18
24
|
return false;
|
|
19
25
|
}
|
|
20
|
-
return isSelect<T, S, F>(validator, schema.items as S, rootSchema);
|
|
26
|
+
return isSelect<T, S, F>(validator, schema.items as S, rootSchema, experimental_customMergeAllOf);
|
|
21
27
|
}
|
package/src/schema/isSelect.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import isConstant from '../isConstant';
|
|
2
|
-
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType } from '../types';
|
|
2
|
+
import { FormContextType, RJSFSchema, StrictRJSFSchema, ValidatorType, Experimental_CustomMergeAllOf } from '../types';
|
|
3
3
|
import retrieveSchema from './retrieveSchema';
|
|
4
4
|
|
|
5
5
|
/** Checks to see if the `schema` combination represents a select
|
|
@@ -7,14 +7,16 @@ import retrieveSchema from './retrieveSchema';
|
|
|
7
7
|
* @param validator - An implementation of the `ValidatorType` interface that will be used when necessary
|
|
8
8
|
* @param theSchema - The schema for which check for a select flag is desired
|
|
9
9
|
* @param [rootSchema] - The root schema, used to primarily to look up `$ref`s
|
|
10
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
10
11
|
* @returns - True if schema contains a select, otherwise false
|
|
11
12
|
*/
|
|
12
13
|
export default function isSelect<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
|
|
13
14
|
validator: ValidatorType<T, S, F>,
|
|
14
15
|
theSchema: S,
|
|
15
|
-
rootSchema: S = {} as S
|
|
16
|
+
rootSchema: S = {} as S,
|
|
17
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
16
18
|
) {
|
|
17
|
-
const schema = retrieveSchema<T, S, F>(validator, theSchema, rootSchema, undefined);
|
|
19
|
+
const schema = retrieveSchema<T, S, F>(validator, theSchema, rootSchema, undefined, experimental_customMergeAllOf);
|
|
18
20
|
const altSchemas = schema.oneOf || schema.anyOf;
|
|
19
21
|
if (Array.isArray(schema.enum)) {
|
|
20
22
|
return true;
|
|
@@ -365,13 +365,20 @@ export function resolveAllReferences<S extends StrictRJSFSchema = RJSFSchema>(
|
|
|
365
365
|
* @param theSchema - The schema for which the existing additional properties is desired
|
|
366
366
|
* @param [rootSchema] - The root schema, used to primarily to look up `$ref`s * @param validator
|
|
367
367
|
* @param [aFormData] - The current formData, if any, to assist retrieving a schema
|
|
368
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
368
369
|
* @returns - The updated schema with additional properties stubbed
|
|
369
370
|
*/
|
|
370
371
|
export function stubExistingAdditionalProperties<
|
|
371
372
|
T = any,
|
|
372
373
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
373
374
|
F extends FormContextType = any
|
|
374
|
-
>(
|
|
375
|
+
>(
|
|
376
|
+
validator: ValidatorType<T, S, F>,
|
|
377
|
+
theSchema: S,
|
|
378
|
+
rootSchema?: S,
|
|
379
|
+
aFormData?: T,
|
|
380
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
381
|
+
): S {
|
|
375
382
|
// Clone the schema so that we don't ruin the consumer's original
|
|
376
383
|
const schema = {
|
|
377
384
|
...theSchema,
|
|
@@ -393,7 +400,8 @@ export function stubExistingAdditionalProperties<
|
|
|
393
400
|
validator,
|
|
394
401
|
{ $ref: get(schema.additionalProperties, [REF_KEY]) } as S,
|
|
395
402
|
rootSchema,
|
|
396
|
-
formData as T
|
|
403
|
+
formData as T,
|
|
404
|
+
experimental_customMergeAllOf
|
|
397
405
|
);
|
|
398
406
|
} else if ('type' in schema.additionalProperties!) {
|
|
399
407
|
additionalProperties = { ...schema.additionalProperties };
|
|
@@ -456,7 +464,8 @@ export function retrieveSchemaInternal<
|
|
|
456
464
|
rootSchema,
|
|
457
465
|
expandAllBranches,
|
|
458
466
|
recurseList,
|
|
459
|
-
rawFormData
|
|
467
|
+
rawFormData,
|
|
468
|
+
experimental_customMergeAllOf
|
|
460
469
|
);
|
|
461
470
|
return resolvedSchemas.flatMap((s: S) => {
|
|
462
471
|
let resolvedSchema = s;
|
|
@@ -507,7 +516,13 @@ export function retrieveSchemaInternal<
|
|
|
507
516
|
const hasAdditionalProperties =
|
|
508
517
|
ADDITIONAL_PROPERTIES_KEY in resolvedSchema && resolvedSchema.additionalProperties !== false;
|
|
509
518
|
if (hasAdditionalProperties) {
|
|
510
|
-
return stubExistingAdditionalProperties<T, S, F>(
|
|
519
|
+
return stubExistingAdditionalProperties<T, S, F>(
|
|
520
|
+
validator,
|
|
521
|
+
resolvedSchema,
|
|
522
|
+
rootSchema,
|
|
523
|
+
rawFormData as T,
|
|
524
|
+
experimental_customMergeAllOf
|
|
525
|
+
);
|
|
511
526
|
}
|
|
512
527
|
|
|
513
528
|
return resolvedSchema;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
2
|
import has from 'lodash/has';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Experimental_CustomMergeAllOf,
|
|
6
|
+
FormContextType,
|
|
7
|
+
GenericObjectType,
|
|
8
|
+
RJSFSchema,
|
|
9
|
+
StrictRJSFSchema,
|
|
10
|
+
ValidatorType,
|
|
11
|
+
} from '../types';
|
|
5
12
|
import { PROPERTIES_KEY, REF_KEY } from '../constants';
|
|
6
13
|
import retrieveSchema from './retrieveSchema';
|
|
7
14
|
|
|
@@ -51,6 +58,7 @@ const NO_VALUE = Symbol('no Value');
|
|
|
51
58
|
* @param [newSchema] - The new schema for which the data is being sanitized
|
|
52
59
|
* @param [oldSchema] - The old schema from which the data originated
|
|
53
60
|
* @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined
|
|
61
|
+
* @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas
|
|
54
62
|
* @returns - The new form data, with all the fields uniquely associated with the old schema set
|
|
55
63
|
* to `undefined`. Will return `undefined` if the new schema is not an object containing properties.
|
|
56
64
|
*/
|
|
@@ -58,7 +66,14 @@ export default function sanitizeDataForNewSchema<
|
|
|
58
66
|
T = any,
|
|
59
67
|
S extends StrictRJSFSchema = RJSFSchema,
|
|
60
68
|
F extends FormContextType = any
|
|
61
|
-
>(
|
|
69
|
+
>(
|
|
70
|
+
validator: ValidatorType<T, S, F>,
|
|
71
|
+
rootSchema: S,
|
|
72
|
+
newSchema?: S,
|
|
73
|
+
oldSchema?: S,
|
|
74
|
+
data: any = {},
|
|
75
|
+
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
76
|
+
): T {
|
|
62
77
|
// By default, we will clear the form data
|
|
63
78
|
let newFormData;
|
|
64
79
|
// If the new schema is of type object and that object contains a list of properties
|
|
@@ -82,10 +97,22 @@ export default function sanitizeDataForNewSchema<
|
|
|
82
97
|
let newKeyedSchema: S = get(newSchema, [PROPERTIES_KEY, key], {});
|
|
83
98
|
// Resolve the refs if they exist
|
|
84
99
|
if (has(oldKeyedSchema, REF_KEY)) {
|
|
85
|
-
oldKeyedSchema = retrieveSchema<T, S, F>(
|
|
100
|
+
oldKeyedSchema = retrieveSchema<T, S, F>(
|
|
101
|
+
validator,
|
|
102
|
+
oldKeyedSchema,
|
|
103
|
+
rootSchema,
|
|
104
|
+
formValue,
|
|
105
|
+
experimental_customMergeAllOf
|
|
106
|
+
);
|
|
86
107
|
}
|
|
87
108
|
if (has(newKeyedSchema, REF_KEY)) {
|
|
88
|
-
newKeyedSchema = retrieveSchema<T, S, F>(
|
|
109
|
+
newKeyedSchema = retrieveSchema<T, S, F>(
|
|
110
|
+
validator,
|
|
111
|
+
newKeyedSchema,
|
|
112
|
+
rootSchema,
|
|
113
|
+
formValue,
|
|
114
|
+
experimental_customMergeAllOf
|
|
115
|
+
);
|
|
89
116
|
}
|
|
90
117
|
// Now get types and see if they are the same
|
|
91
118
|
const oldSchemaTypeForKey = get(oldKeyedSchema, 'type');
|
|
@@ -104,7 +131,8 @@ export default function sanitizeDataForNewSchema<
|
|
|
104
131
|
rootSchema,
|
|
105
132
|
newKeyedSchema,
|
|
106
133
|
oldKeyedSchema,
|
|
107
|
-
formValue
|
|
134
|
+
formValue,
|
|
135
|
+
experimental_customMergeAllOf
|
|
108
136
|
);
|
|
109
137
|
if (itemData !== undefined || newSchemaTypeForKey === 'array') {
|
|
110
138
|
// only put undefined values for the array type and not the object type
|
|
@@ -154,10 +182,22 @@ export default function sanitizeDataForNewSchema<
|
|
|
154
182
|
!Array.isArray(newSchemaItems)
|
|
155
183
|
) {
|
|
156
184
|
if (has(oldSchemaItems, REF_KEY)) {
|
|
157
|
-
oldSchemaItems = retrieveSchema<T, S, F>(
|
|
185
|
+
oldSchemaItems = retrieveSchema<T, S, F>(
|
|
186
|
+
validator,
|
|
187
|
+
oldSchemaItems as S,
|
|
188
|
+
rootSchema,
|
|
189
|
+
data as T,
|
|
190
|
+
experimental_customMergeAllOf
|
|
191
|
+
);
|
|
158
192
|
}
|
|
159
193
|
if (has(newSchemaItems, REF_KEY)) {
|
|
160
|
-
newSchemaItems = retrieveSchema<T, S, F>(
|
|
194
|
+
newSchemaItems = retrieveSchema<T, S, F>(
|
|
195
|
+
validator,
|
|
196
|
+
newSchemaItems as S,
|
|
197
|
+
rootSchema,
|
|
198
|
+
data as T,
|
|
199
|
+
experimental_customMergeAllOf
|
|
200
|
+
);
|
|
161
201
|
}
|
|
162
202
|
// Now get types and see if they are the same
|
|
163
203
|
const oldSchemaType = get(oldSchemaItems, 'type');
|
|
@@ -172,7 +212,8 @@ export default function sanitizeDataForNewSchema<
|
|
|
172
212
|
rootSchema,
|
|
173
213
|
newSchemaItems as S,
|
|
174
214
|
oldSchemaItems as S,
|
|
175
|
-
aValue
|
|
215
|
+
aValue,
|
|
216
|
+
experimental_customMergeAllOf
|
|
176
217
|
);
|
|
177
218
|
if (itemValue !== undefined && (maxItems < 0 || newValue.length < maxItems)) {
|
|
178
219
|
newValue.push(itemValue);
|
package/src/schema/toIdSchema.ts
CHANGED
|
@@ -41,7 +41,7 @@ function toIdSchemaInternal<T = any, S extends StrictRJSFSchema = RJSFSchema, F
|
|
|
41
41
|
experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>
|
|
42
42
|
): IdSchema<T> {
|
|
43
43
|
if (REF_KEY in schema || DEPENDENCIES_KEY in schema || ALL_OF_KEY in schema) {
|
|
44
|
-
const _schema = retrieveSchema<T, S, F>(validator, schema, rootSchema, formData);
|
|
44
|
+
const _schema = retrieveSchema<T, S, F>(validator, schema, rootSchema, formData, experimental_customMergeAllOf);
|
|
45
45
|
const sameSchemaIndex = _recurseList.findIndex((item) => isEqual(item, _schema));
|
|
46
46
|
if (sameSchemaIndex === -1) {
|
|
47
47
|
return toIdSchemaInternal<T, S, F>(
|