Repository: nestjs/swagger
Pull request #3369 (2025-03-31 12:04:39)

fix: recursive schema reference handling #3368
## PR Checklist
Please check if your PR fulfills the following requirements:

- [x] The commit message follows our guidelines: https://github.com/nestjs/nest/blob/master/CONTRIBUTING.md
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)


## PR Type
What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->
- [x] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Other... Please describe:

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

Issue Number: [#3368](https://github.com/nestjs/swagger/issues/3368)


## What is the new behavior?
Generated schemas correctly reference the custom schema names:
```
"#/components/schemas/MenuNode"
```

## Does this PR introduce a breaking change?
- [ ] Yes
- [x] No



Patch:
diff --git a/lib/services/schema-object-factory.ts b/lib/services/schema-object-factory.ts
index 076da32f..eb2f1b52 100644
--- a/lib/services/schema-object-factory.ts
+++ b/lib/services/schema-object-factory.ts
@@ -456,7 +456,9 @@ export class SchemaObjectFactory {
         `A circular dependency has been detected (property key: "${key}"). Please, make sure that each side of a bidirectional relationships are using lazy resolvers ("type: () => ClassType").`
       );
     }
-    let schemaObjectName = (trueMetadataType as Function).name;
+    let { schemaName: schemaObjectName } = this.getSchemaMetadata(
+      trueMetadataType as Function | Type<unknown>
+    );
 
     if (
       !(schemaObjectName in schemas) &&


Test patch:
diff --git a/test/services/schema-object-factory.spec.ts b/test/services/schema-object-factory.spec.ts
index 1c4427a1..f4c1f689 100644
--- a/test/services/schema-object-factory.spec.ts
+++ b/test/services/schema-object-factory.spec.ts
@@ -453,6 +453,32 @@ describe('SchemaObjectFactory', () => {
         expect(Object.keys(schemas)).toContain('UpdateUser');
       });
 
+      it('should correctly handle recursive schema references in ApiSchema decorator', () => {
+        @ApiSchema({ name: 'MenuNode' })
+        class MenuNodeDto {
+          @ApiProperty({ type: () => MenuNodeDto })
+          childNode: MenuNodeDto;
+        }
+
+        @ApiSchema({ name: 'Menu' })
+        class MenuDto {
+          @ApiProperty({ type: () => MenuNodeDto })
+          rootNode: MenuNodeDto;
+        }
+
+        const schemas: Record<string, SchemasObject> = {};
+
+        schemaObjectFactory.exploreModelSchema(MenuDto, schemas);
+
+        expect(schemas['MenuNode'].properties['childNode']['$ref']).toEqual(
+          '#/components/schemas/MenuNode'
+        );
+
+        expect(schemas['Menu'].properties['rootNode']['$ref']).toEqual(
+          '#/components/schemas/MenuNode'
+        );
+      });
+
       it('should use the the description if provided', () => {
         @ApiSchema({
           description: 'Represents a user.'