diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/operation.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/operation.ts index 51a7c224cd..c559f4329e 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/operation.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/operation.ts @@ -130,15 +130,29 @@ export const operationClasses = ({ } } + // Map path to PascalCase class names + const transformedPath = path.map((value) => + operationClassName({ + context, + value, + }), + ); + + // Remove duplicate class names to prevent circular references + // Keep only the first occurrence of each class name + const uniquePath: Array = []; + const seen = new Set(); + for (const name of transformedPath) { + if (!seen.has(name)) { + seen.add(name); + uniquePath.push(name); + } + } + classNames.set(rootClass, { className: finalClassName, methodName: methodName || getOperationMethodName({ operation, plugin }), - path: path.map((value) => - operationClassName({ - context, - value, - }), - ), + path: uniquePath, }); } diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts index f799a89e12..16868a1f69 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts @@ -179,8 +179,29 @@ const generateClassSdk = ({ symbolParentClass.placeholder !== symbolCurrentClass.placeholder ) { const parentClass = sdkClasses.get(symbolParentClass.id)!; - parentClass.classes.add(symbolCurrentClass.id); - sdkClasses.set(symbolParentClass.id, parentClass); + // Check if adding this child would create a cycle + // A cycle exists if the current class is an ancestor of the parent class + const wouldCreateCycle = ( + childId: number, + ancestorId: number, + ): boolean => { + const child = sdkClasses.get(childId); + if (!child) return false; + if (child.id === ancestorId) return true; + for (const grandchildId of child.classes) { + if (wouldCreateCycle(grandchildId, ancestorId)) { + return true; + } + } + return false; + }; + + if ( + !wouldCreateCycle(symbolCurrentClass.id, symbolParentClass.id) + ) { + parentClass.classes.add(symbolCurrentClass.id); + sdkClasses.set(symbolParentClass.id, parentClass); + } } }