diff --git a/packages/utils/src/schema/retrieveSchema.ts b/packages/utils/src/schema/retrieveSchema.ts index 0f46632f1c..2c9225f628 100644 --- a/packages/utils/src/schema/retrieveSchema.ts +++ b/packages/utils/src/schema/retrieveSchema.ts @@ -412,9 +412,24 @@ export function retrieveSchemaInternal< return [...(allOf as S[]), restOfSchema as S]; } try { + const withContainsSchemas = [] as S[]; + const withoutContainsSchemas = [] as S[]; + resolvedSchema.allOf?.forEach((s) => { + if (typeof s === 'object' && s.contains) { + withContainsSchemas.push(s as S); + } else { + withoutContainsSchemas.push(s as S); + } + }); + if (withContainsSchemas.length) { + resolvedSchema = { ...resolvedSchema, allOf: withoutContainsSchemas }; + } resolvedSchema = mergeAllOf(resolvedSchema, { deep: false, } as Options) as S; + if (withContainsSchemas.length) { + resolvedSchema.allOf = withContainsSchemas; + } } catch (e) { console.warn('could not merge subschemas in allOf:\n', e); const { allOf, ...resolvedSchemaWithoutAllOf } = resolvedSchema; diff --git a/packages/utils/test/schema/retrieveSchemaTest.ts b/packages/utils/test/schema/retrieveSchemaTest.ts index 9f91d199b8..2e13c7b262 100644 --- a/packages/utils/test/schema/retrieveSchemaTest.ts +++ b/packages/utils/test/schema/retrieveSchemaTest.ts @@ -759,6 +759,81 @@ export default function retrieveSchemaTest(testValidator: TestValidatorType) { type: 'string', }); }); + it('should not merge `allOf.contains` schemas', () => { + // https://github.com/rjsf-team/react-jsonschema-form/issues/2923#issuecomment-1946034240 + const schema: RJSFSchema = { + type: 'array', + items: { + type: 'object', + properties: { + a: { + type: 'string', + }, + }, + }, + allOf: [ + { + maxItems: 5, + }, + { + contains: { + type: 'object', + properties: { + a: { + pattern: '1', + }, + }, + }, + }, + { + contains: { + type: 'object', + properties: { + a: { + pattern: '2', + }, + }, + }, + }, + ], + }; + const rootSchema: RJSFSchema = { definitions: {} }; + const formData = {}; + expect(retrieveSchema(testValidator, schema, rootSchema, formData)).toEqual({ + type: 'array', + items: { + type: 'object', + properties: { + a: { + type: 'string', + }, + }, + }, + maxItems: 5, + allOf: [ + { + contains: { + type: 'object', + properties: { + a: { + pattern: '1', + }, + }, + }, + }, + { + contains: { + type: 'object', + properties: { + a: { + pattern: '2', + }, + }, + }, + }, + ], + }); + }); it('should not merge incompatible types', () => { const schema: RJSFSchema = { allOf: [{ type: 'string' }, { type: 'boolean' }],