From e2fd79c2ec7b9d6ed75ebc6f301160eb0c2e96ba Mon Sep 17 00:00:00 2001 From: harsha-iiiv Date: Sun, 8 Jun 2025 23:10:43 +0530 Subject: [PATCH] feat: Enhance schema mapping with cycle protection - Added cycle detection to the mapOpenApiSchemaToJsonSchema function to prevent infinite recursion when processing schemas. - Introduced a WeakSet to track visited schema objects, ensuring robust handling of circular references. --- src/parser/extract-tools.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/parser/extract-tools.ts b/src/parser/extract-tools.ts index 8816095..1741494 100644 --- a/src/parser/extract-tools.ts +++ b/src/parser/extract-tools.ts @@ -153,13 +153,15 @@ export function generateInputSchemaAndDetails(operation: OpenAPIV3.OperationObje } /** - * Maps an OpenAPI schema to a JSON Schema + * Maps an OpenAPI schema to a JSON Schema with cycle protection. * * @param schema OpenAPI schema object or reference + * @param seen WeakSet tracking already visited schema objects * @returns JSON Schema representation */ export function mapOpenApiSchemaToJsonSchema( - schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject + schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, + seen: WeakSet = new WeakSet() ): JSONSchema7 | boolean { // Handle reference objects if ('$ref' in schema) { @@ -170,6 +172,13 @@ export function mapOpenApiSchemaToJsonSchema( // Handle boolean schemas if (typeof schema === 'boolean') return schema; + // Detect cycles + if (seen.has(schema)) { + console.warn('Cycle detected in schema, returning generic object to break recursion.'); + return { type: 'object' }; + } + seen.add(schema); + // Create a copy of the schema to modify const jsonSchema: JSONSchema7 = { ...schema } as any; @@ -202,7 +211,7 @@ export function mapOpenApiSchemaToJsonSchema( for (const [key, propSchema] of Object.entries(jsonSchema.properties)) { if (typeof propSchema === 'object' && propSchema !== null) { - mappedProps[key] = mapOpenApiSchemaToJsonSchema(propSchema as OpenAPIV3.SchemaObject); + mappedProps[key] = mapOpenApiSchemaToJsonSchema(propSchema as OpenAPIV3.SchemaObject, seen); } else if (typeof propSchema === 'boolean') { mappedProps[key] = propSchema; } @@ -218,9 +227,11 @@ export function mapOpenApiSchemaToJsonSchema( jsonSchema.items !== null ) { jsonSchema.items = mapOpenApiSchemaToJsonSchema( - jsonSchema.items as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject + jsonSchema.items as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, + seen ); } + seen.delete(schema); return jsonSchema; }