Skip to content

Commit

Permalink
Fix incorrect allOf merging (fix rjsf-team#2923) (Reimplement rjsf-te…
Browse files Browse the repository at this point in the history
…am#3025) (rjsf-team#3227)

Co-authored-by: Sergey Alimov <sergey.alimov@gmail.com>
Co-authored-by: Heath C <51679588+heath-freenome@users.noreply.github.com>
Fixes rjsf-team#2923
  • Loading branch information
nickgros authored and shijistar committed Jun 8, 2023
1 parent b9a7aa8 commit 1945907
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 43 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion packages/utils/src/schema/getDefaultFormState.ts
Expand Up @@ -96,13 +96,14 @@ export function computeDefaults<
S extends StrictRJSFSchema = RJSFSchema
>(
validator: ValidatorType<T, S>,
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)) {
Expand Down
36 changes: 4 additions & 32 deletions 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,
Expand Down Expand Up @@ -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<T, S>(
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;
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/schema/toPathSchema.ts
Expand Up @@ -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);
}
Expand Down
18 changes: 18 additions & 0 deletions packages/utils/test/schema/getDefaultFormStateTest.ts
Expand Up @@ -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", () => {
Expand Down
52 changes: 45 additions & 7 deletions packages/utils/test/schema/retrieveSchemaTest.ts
Expand Up @@ -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",
},
},
Expand Down

0 comments on commit 1945907

Please sign in to comment.