Repository: nestjs/swagger
Pull request #2238 (2023-01-11 20:16:37)

fix: number enum generated schema type
## 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)

## 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?

Currently, if you create a number enum property like this:

```typescript
@ApiParam({ enum: [1, 2, 3] })
```

It will then generate a correct schema for this param:

```json
{
  "type": "number",
  "enum": [1, 2, 3]
}
```

But if you add an “enumName“ parameter, so that the enum will get its own schema entry like this:

```typescript
@ApiParam({ enum: [1, 2, 3], enumName: "ParamEnumName" })
```

It will change the type of the enum in the schema from 'number' to 'string':

```json
{
  "ParamEnumName": {
    "type": "string",
    "enum": [
      1,
      2,
      3
    ]
  }
}
```

## What is the new behavior?

I made it so it saves the type, if is was given before.

So if we take our previous example:

```typescript
@ApiParam({ enum: [1, 2, 3], enumName: "ParamEnumName" })
```

It will now generate a correct schema for this enum:

```json
{
  "ParamEnumName": {
    "type": "number",
    "enum": [
      1,
      2,
      3
    ]
  }
}
```

## 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/services/schema-object-factory.ts b/lib/services/schema-object-factory.ts
index 0a9d345d..93999084 100644
--- a/lib/services/schema-object-factory.ts
+++ b/lib/services/schema-object-factory.ts
@@ -254,7 +254,7 @@ export class SchemaObjectFactory {
         : param.schema['enum'];
 
       schemas[enumName] = {
-        type: 'string',
+        type: param.schema?.['type'] ?? 'string',
         enum: _enum
       };
     }


Test patch:
diff --git a/test/explorer/swagger-explorer.spec.ts b/test/explorer/swagger-explorer.spec.ts
index 5e91b9e8..72c6417e 100644
--- a/test/explorer/swagger-explorer.spec.ts
+++ b/test/explorer/swagger-explorer.spec.ts
@@ -915,6 +915,19 @@ describe('SwaggerExplorer', () => {
       }
     }
 
+    @Controller('')
+    class Bar2Controller {
+      @Get('bars/:objectId')
+      @ApiParam({
+        name: 'objectId',
+        enum: [1, 2, 3],
+        enumName: 'NumberEnum'
+      })
+      findBar(): Promise<Foo> {
+        return Promise.resolve(null);
+      }
+    }
+
     it('should properly define enums', () => {
       const explorer = new SwaggerExplorer(schemaObjectFactory);
       const config = new ApplicationConfig();
@@ -1052,6 +1065,33 @@ describe('SwaggerExplorer', () => {
         }
       ]);
     });
+
+    it('should properly define number enum as schema', () => {
+      const explorer = new SwaggerExplorer(schemaObjectFactory);
+
+      const schema = explorer.getSchemas();
+      const routes = explorer.exploreController(
+        {
+          instance: new Bar2Controller(),
+          metatype: Bar2Controller
+        } as InstanceWrapper<Bar2Controller>,
+        new ApplicationConfig(),
+        'modulePath',
+        'globalPrefix'
+      );
+
+      expect(schema.NumberEnum).toEqual({ type: 'number', enum: [1, 2, 3] });
+      expect(routes[0].root.parameters).toEqual([
+        {
+          in: 'path',
+          name: 'objectId',
+          required: true,
+          schema: {
+            $ref: '#/components/schemas/NumberEnum'
+          }
+        }
+      ]);
+    });
   });
 
   describe('when headers are defined', () => {