diff --git a/.changeset/brave-doors-glow.md b/.changeset/brave-doors-glow.md new file mode 100644 index 000000000..f9e581e46 --- /dev/null +++ b/.changeset/brave-doors-glow.md @@ -0,0 +1,5 @@ +--- +"@gitbook/react-openapi": patch +--- + +Handle non-array required field in OpenAPI schema to fix TypeError with specs using boolean required values diff --git a/packages/react-openapi/src/OpenAPISchema.test.ts b/packages/react-openapi/src/OpenAPISchema.test.ts index 8f7c10e9c..1def1780e 100644 --- a/packages/react-openapi/src/OpenAPISchema.test.ts +++ b/packages/react-openapi/src/OpenAPISchema.test.ts @@ -185,6 +185,60 @@ describe('getSchemaAlternatives', () => { }); }); + it('should handle non-standard boolean required values without throwing', () => { + // Some specs (e.g. Trustly) use `"required": true` on properties + // instead of the standard `string[]` format. This should not throw. + const schema = { + allOf: [ + { + type: 'object', + properties: { + name: { type: 'string' }, + }, + required: true as any, + }, + { + type: 'object', + properties: { + email: { type: 'string' }, + }, + required: ['email'], + }, + ], + } as any; + + const result = getSchemaAlternatives(schema); + expect(result).toBeDefined(); + // The boolean `required: true` should be ignored, only the valid array is kept + expect(result?.schemas[0]?.required).toEqual(['email']); + }); + + it('should handle boolean required on both schemas without throwing', () => { + const schema = { + allOf: [ + { + type: 'object', + properties: { + name: { type: 'string' }, + }, + required: true as any, + }, + { + type: 'object', + properties: { + email: { type: 'string' }, + }, + required: false as any, + }, + ], + } as any; + + const result = getSchemaAlternatives(schema); + expect(result).toBeDefined(); + // Boolean required values should not cause a crash, result is an empty array + expect(result?.schemas[0]?.required).toEqual([]); + }); + describe('safe merging with allOf', () => { it('should merge objects with safe extensions', () => { expect( diff --git a/packages/react-openapi/src/OpenAPISchema.tsx b/packages/react-openapi/src/OpenAPISchema.tsx index e070681f4..67f3a9768 100644 --- a/packages/react-openapi/src/OpenAPISchema.tsx +++ b/packages/react-openapi/src/OpenAPISchema.tsx @@ -1105,15 +1105,19 @@ function mergeRequiredFields( schemaOrRef: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, latestAncestor: OpenAPIV3.SchemaObject | undefined ) { - if (!schemaOrRef.required && !latestAncestor?.required) { + const ancestorRequired = Array.isArray(latestAncestor?.required) + ? latestAncestor.required + : undefined; + + if (checkIsReference(schemaOrRef)) { + return ancestorRequired; + } + + const schemaRequired = Array.isArray(schemaOrRef.required) ? schemaOrRef.required : undefined; + + if (!ancestorRequired && !schemaRequired) { return undefined; } - if (checkIsReference(schemaOrRef)) { - return latestAncestor?.required; - } - - return Array.from( - new Set([...(latestAncestor?.required || []), ...(schemaOrRef.required || [])]) - ); + return Array.from(new Set([...(ancestorRequired || []), ...(schemaRequired || [])])); }