Repository: nestjs/swagger
Pull request #2869 (2024-03-09 10:23:33)

fix(plugin): ensure open-api docs generation for types named with Promise or Observable
## 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. -->

I've encountered an issue with NestJS Swagger where automatic API documentation generation does not properly handle types that include the `Promise` or `Observable` keywords. This occurs when using `@Body()`, `@Query()`, or return types in controllers that are intended to be documented by Swagger.

Issue Number: N/A

## What is the new behavior?

Types that include `Promise` or `Observable` should be accurately reflected in the Swagger documentation.

## Does this PR introduce a breaking change?
- [ ] Yes
- [x] No

<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->


## Other information



Patch:
diff --git a/lib/plugin/utils/plugin-utils.ts b/lib/plugin/utils/plugin-utils.ts
index 33bfe414..7d1bd208 100644
--- a/lib/plugin/utils/plugin-utils.ts
+++ b/lib/plugin/utils/plugin-utils.ts
@@ -125,7 +125,7 @@ export function getTypeReferenceAsString(
 }
 
 export function isPromiseOrObservable(type: string) {
-  return type.includes('Promise') || type.includes('Observable');
+  return type.includes('Promise<') || type.includes('Observable<');
 }
 
 export function hasPropertyKey(


Test patch:
diff --git a/test/plugin/fixtures/app.controller.ts b/test/plugin/fixtures/app.controller.ts
index e407a9db..a73ae073 100644
--- a/test/plugin/fixtures/app.controller.ts
+++ b/test/plugin/fixtures/app.controller.ts
@@ -3,6 +3,10 @@ import { ApiOperation } from '@nestjs/swagger';
 
 class Cat {}
 
+class PromiseCat {}
+
+class ObservableCat {}
+
 @Controller('cats')
 export class AppController {
   onApplicationBootstrap() {}
@@ -39,6 +43,24 @@ export class AppController {
   @Post()
   async testCreate2(): Promise<Cat> {}
 
+  /**
+   * create a test PromiseCat
+   *
+   * @returns {Promise<PromiseCat>>}
+   * @memberof AppController
+   */
+  @Post()
+  async testCreate3(): Promise<PromiseCat> {}
+
+  /**
+   * create a test ObservableCat
+   *
+   * @returns {Promise<ObservableCat>}
+   * @memberof AppController
+   */
+  @Post()
+  async testCreate4(): Promise<ObservableCat> {}
+
   /**
    * find a Cat
    */
@@ -68,6 +90,10 @@ const common_1 = require(\"@nestjs/common\");
 const swagger_1 = require(\"@nestjs/swagger\");
 class Cat {
 }
+class PromiseCat {
+}
+class ObservableCat {
+}
 let AppController = exports.AppController = class AppController {
     onApplicationBootstrap() { }
     /**
@@ -95,6 +121,20 @@ let AppController = exports.AppController = class AppController {
      * @memberof AppController
      */
     async testCreate2() { }
+    /**
+     * create a test PromiseCat
+     *
+     * @returns {Promise<PromiseCat>>}
+     * @memberof AppController
+     */
+    async testCreate3() { }
+    /**
+     * create a test ObservableCat
+     *
+     * @returns {Promise<ObservableCat>}
+     * @memberof AppController
+     */
+    async testCreate4() { }
     /**
      * find a Cat
      */
@@ -122,6 +162,16 @@ __decorate([
     (0, common_1.Post)(),
     openapi.ApiResponse({ status: 201, type: Cat })
 ], AppController.prototype, \"testCreate2\", null);
+__decorate([
+    openapi.ApiOperation({ summary: \"create a test PromiseCat\" }),
+    (0, common_1.Post)(),
+    openapi.ApiResponse({ status: 201, type: PromiseCat })
+], AppController.prototype, \"testCreate3\", null);
+__decorate([
+    openapi.ApiOperation({ summary: \"create a test ObservableCat\" }),
+    (0, common_1.Post)(),
+    openapi.ApiResponse({ status: 201, type: ObservableCat })
+], AppController.prototype, \"testCreate4\", null);
 __decorate([
     (0, swagger_1.ApiOperation)({ summary: \"find a Cat\" }),
     Get(),