diff --git a/CHANGELOG.md b/CHANGELOG.md index d25d85ee16..0826d50c71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,12 +17,13 @@ should change the heading of the (upcoming) version to include a major version b --> # 5.0.0-beta-15 -# @rjsf/core +## @rjsf/core - Pass the `schema` along to the `ArrayFieldItemTemplate` as part of the fix for [#3253](https://github.com/rjsf-team/react-jsonschema-form/issues/3253) - Tweak Babel configuration to emit ES5-compatible output files, fixing [#3240](https://github.com/rjsf-team/react-jsonschema-form/issues/3240) -# @rjsf/utils +## @rjsf/utils - Update the `ArrayFieldItemTemplate` to add `schema` as part of the fix for [#3253](https://github.com/rjsf-team/react-jsonschema-form/issues/3253) +- Fix improper merging of nested `allOf`s ([#3025](https://github.com/rjsf-team/react-jsonschema-form/pull/3025), [#3227](https://github.com/rjsf-team/react-jsonschema-form/pull/3227)), fixing [#2923](https://github.com/rjsf-team/react-jsonschema-form/pull/2929) ## Dev / docs / playground - Fixed the documentation for `ArrayFieldItemTemplate` as part of the fix for [#3253](https://github.com/rjsf-team/react-jsonschema-form/issues/3253) diff --git a/packages/utils/src/schema/getDefaultFormState.ts b/packages/utils/src/schema/getDefaultFormState.ts index a67ee721a5..be29fd8e2c 100644 --- a/packages/utils/src/schema/getDefaultFormState.ts +++ b/packages/utils/src/schema/getDefaultFormState.ts @@ -96,13 +96,14 @@ export function computeDefaults< S extends StrictRJSFSchema = RJSFSchema >( validator: ValidatorType, - schema: S, + rawSchema: S, parentDefaults?: T, rootSchema: S = {} as S, rawFormData?: T, includeUndefinedValues: boolean | "excludeObjectChildren" = false ): T | T[] | undefined { const formData = isObject(rawFormData) ? rawFormData : {}; + let schema: S = isObject(rawSchema) ? rawSchema : ({} as S); // Compute the defaults recursively: give highest priority to deepest nodes. let defaults: T | T[] | undefined = parentDefaults; if (isObject(defaults) && isObject(schema.default)) { diff --git a/packages/utils/src/schema/retrieveSchema.ts b/packages/utils/src/schema/retrieveSchema.ts index d120a5ca11..2da8c4a453 100644 --- a/packages/utils/src/schema/retrieveSchema.ts +++ b/packages/utils/src/schema/retrieveSchema.ts @@ -1,6 +1,6 @@ import get from "lodash/get"; import set from "lodash/set"; -import mergeAllOf from "json-schema-merge-allof"; +import mergeAllOf, { Options } from "json-schema-merge-allof"; import { ADDITIONAL_PROPERTIES_KEY, @@ -242,40 +242,12 @@ export default function retrieveSchema< } const formData: GenericObjectType = rawFormData || {}; - // For each level of the dependency, we need to recursively determine the appropriate resolved schema given the current state of formData. - // Otherwise, nested allOf subschemas will not be correctly displayed. - if (resolvedSchema.properties) { - const properties: GenericObjectType = {}; - - Object.entries(resolvedSchema.properties).forEach((entries) => { - const propName = entries[0]; - const propSchema = entries[1] as S; - const rawPropData = formData[propName]; - const propData = isObject(rawPropData) ? rawPropData : {}; - const resolvedPropSchema = retrieveSchema( - validator, - propSchema, - rootSchema, - propData - ); - - properties[propName] = resolvedPropSchema; - - if ( - propSchema !== resolvedPropSchema && - resolvedSchema.properties !== properties - ) { - resolvedSchema = { ...resolvedSchema, properties }; - } - }); - } if (ALL_OF_KEY in schema) { try { - resolvedSchema = mergeAllOf({ - ...resolvedSchema, - allOf: resolvedSchema.allOf, - }) as S; + resolvedSchema = mergeAllOf(resolvedSchema, { + deep: false, + } as Options) as S; } catch (e) { console.warn("could not merge subschemas in allOf:\n" + e); const { allOf, ...resolvedSchemaWithoutAllOf } = resolvedSchema; diff --git a/packages/utils/src/schema/toPathSchema.ts b/packages/utils/src/schema/toPathSchema.ts index 7dc7ea7fbd..84279fab8f 100644 --- a/packages/utils/src/schema/toPathSchema.ts +++ b/packages/utils/src/schema/toPathSchema.ts @@ -54,7 +54,7 @@ export default function toPathSchema< if ( ADDITIONAL_PROPERTIES_KEY in schema && - schema[ADDITIONAL_PROPERTIES_KEY] === true + schema[ADDITIONAL_PROPERTIES_KEY] !== false ) { set(pathSchema, RJSF_ADDITONAL_PROPERTIES_FLAG, true); } diff --git a/packages/utils/test/schema/getDefaultFormStateTest.ts b/packages/utils/test/schema/getDefaultFormStateTest.ts index aabd14fd84..beb887b34e 100644 --- a/packages/utils/test/schema/getDefaultFormStateTest.ts +++ b/packages/utils/test/schema/getDefaultFormStateTest.ts @@ -151,6 +151,24 @@ export default function getDefaultFormStateTest( requiredProperty: "foo", }); }); + it("test computeDefaults handles an invalid property schema", () => { + const schema: RJSFSchema = { + type: "object", + properties: { + invalidProperty: "not a valid property value", + }, + } as RJSFSchema; + expect( + computeDefaults( + testValidator, + schema, + undefined, + schema, + undefined, + "excludeObjectChildren" + ) + ).toEqual({}); + }); }); describe("root default", () => { it("should map root schema default to form state, if any", () => { diff --git a/packages/utils/test/schema/retrieveSchemaTest.ts b/packages/utils/test/schema/retrieveSchemaTest.ts index eacdfd74b1..adbccfa2fc 100644 --- a/packages/utils/test/schema/retrieveSchemaTest.ts +++ b/packages/utils/test/schema/retrieveSchemaTest.ts @@ -1205,14 +1205,52 @@ export default function retrieveSchemaTest(testValidator: TestValidatorType) { title: "Breed name", type: "string", }, - Spots: { - default: "small", - enum: ["large", "small"], - title: "Spots", - type: "string", - }, }, - required: ["BreedName", "Spots"], + allOf: [ + { + if: { + required: ["BreedName"], + properties: { + BreedName: { + const: "Alsatian", + }, + }, + }, + then: { + properties: { + Fur: { + default: "brown", + enum: ["black", "brown"], + title: "Fur", + type: "string", + }, + }, + required: ["Fur"], + }, + }, + { + if: { + required: ["BreedName"], + properties: { + BreedName: { + const: "Dalmation", + }, + }, + }, + then: { + properties: { + Spots: { + default: "small", + enum: ["large", "small"], + title: "Spots", + type: "string", + }, + }, + required: ["Spots"], + }, + }, + ], + required: ["BreedName"], title: "Breed", }, },