diff --git a/src/parser/extract-tools.ts b/src/parser/extract-tools.ts index 8816095..4c57050 100644 --- a/src/parser/extract-tools.ts +++ b/src/parser/extract-tools.ts @@ -153,10 +153,14 @@ export function generateInputSchemaAndDetails(operation: OpenAPIV3.OperationObje } /** - * Maps an OpenAPI schema to a JSON Schema + * Converts an OpenAPI schema or reference object to a JSON Schema representation. * - * @param schema OpenAPI schema object or reference - * @returns JSON Schema representation + * Handles composite schemas (`oneOf`, `anyOf`, `allOf`) by merging subschemas and combining enum values. Removes OpenAPI-specific properties and adjusts types for JSON Schema compatibility, including handling of nullable fields. Recursively processes nested object properties and array items. + * + * @param schema - The OpenAPI schema object or reference to convert. + * @returns The corresponding JSON Schema object or boolean schema. + * + * @remark If a `$ref` reference cannot be resolved, returns a generic object schema and logs a warning. */ export function mapOpenApiSchemaToJsonSchema( schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject @@ -171,7 +175,35 @@ export function mapOpenApiSchemaToJsonSchema( if (typeof schema === 'boolean') return schema; // Create a copy of the schema to modify - const jsonSchema: JSONSchema7 = { ...schema } as any; + let jsonSchema: JSONSchema7 = { ...schema } as any; + + if (schema.oneOf || schema.anyOf || schema.allOf) { + const oneSchema = structuredClone(schema.oneOf || schema.anyOf || schema.allOf); + + if (oneSchema) { + const combinedSchema = mapOpenApiSchemaToJsonSchema(oneSchema[0]); + + for (let i = 1; i < oneSchema.length; i++) { + const mappedSubSchema = mapOpenApiSchemaToJsonSchema(oneSchema[i]); + if (typeof mappedSubSchema === 'object' && typeof combinedSchema === 'object') { + // Handle enum values + if (mappedSubSchema.enum) { + if (!combinedSchema.enum) { + combinedSchema.enum = []; + } + // Combine enum values from both schemas + const uniqueEnums = new Set([ + ...combinedSchema.enum, + ...(mappedSubSchema.enum || []) + ]); + combinedSchema.enum = Array.from(uniqueEnums); + } + } + } + + jsonSchema = combinedSchema as JSONSchema7; + } + } // Convert integer type to number (JSON Schema compatible) if (schema.type === 'integer') jsonSchema.type = 'number';