swagger icon indicating copy to clipboard operation
swagger copied to clipboard

@ApiProperty - Include default value when using `enumName`

Open Eirmas opened this issue 2 years ago • 5 comments

Is there an existing issue that is already proposing this?

  • [X] I have searched the existing issues

Is your feature request related to a problem? Please describe it

When using @ApiProperty like this:

@ApiProperty({ enum: SortOrder, default: SortOrder.DESC })

It renders the OpenAPI json like this:

{
    "name": "order",
    "required": true,
    "in": "query",
    "schema": {
        "default": "DESC",
        "enum": [
            "DESC",
            "ASC"
    ],
    "type": "string"
    }
}

However, when adding a reference to the enum using enumName instead to avoid duplicate definitions like this:

@ApiProperty({ enum: SortOrder, default: SortOrder.DESC, enumName: 'SortOrder' })

It renders like this:

{
    "name": "order",
    "required": true,
    "in": "query",
    "schema": {
        "$ref": "#/components/schemas/SortOrder"
    }
}

Here we can see that the default property is lost.

Describe the solution you'd like

Here is a discussion that explains a possible solution: https://github.com/OAI/OpenAPI-Specification/discussions/2948

Teachability, documentation, adoption, migration strategy

No response

What is the motivation / use case for changing the behavior?

Improve user experience when using software like Postman, Swagger or similar

Eirmas avatar Mar 29 '24 00:03 Eirmas

Would you like to create a PR for this issue?

kamilmysliwiec avatar Mar 29 '24 07:03 kamilmysliwiec

スクリーンショット 2024-03-31 11 48 09 ref: https://swagger.io/docs/specification/using-ref/

In v3.1.0, it appears that you can define some sibling elements, but it still don't have default property. ref: https://spec.openapis.org/oas/v3.1.0#reference-object

https://github.com/OAI/OpenAPI-Specification/discussions/2948 In my opinion, the example in this page is no different than the code below.

@ApiProperty({ 
  default: SortOrder.DESC,
  allOf: [
    { $ref: getSchemaPath('SortOrder') },
  ]
})

kimdj2 avatar Mar 31 '24 02:03 kimdj2

@Eirmas , you are right, but the SortOrder schema has the default added there and it is being rendered in the swagger ui as well.

@kamilmysliwiec , I am looking to contribute, Is there any priority on the issues that I can start with?

raj-r3a avatar Aug 02 '24 10:08 raj-r3a

I've ended up patching @nestjs/swagger like this:

diff --git a/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js b/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js
index b5c6978..dd9883a 100644
--- a/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js
+++ b/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js
@@ -167,16 +167,16 @@ class SchemaObjectFactory {
         }
         const enumName = metadata.enumName;
         const $ref = (0, utils_1.getSchemaPath)(enumName);
-        const additionalParams = ['description', 'deprecated', 'default'];
+        const additionalParams = ['description'];
         const additionalFields = additionalParams.reduce((acc, param) => (Object.assign(Object.assign({}, acc), (metadata[param] && { [param]: metadata[param] }))), {});
         const enumType = (_a = (metadata.isArray ? metadata.items['type'] : metadata.type)) !== null && _a !== void 0 ? _a : 'string';
         schemas[enumName] = Object.assign(Object.assign({ type: enumType }, additionalFields), { enum: metadata.isArray && metadata.items
                 ? metadata.items['enum']
                 : metadata.enum });
         const _schemaObject = Object.assign(Object.assign({}, metadata), { name: metadata.name || key, type: metadata.isArray ? 'array' : 'string' });
-        const refHost = metadata.isArray ? { items: { $ref } } : { $ref };
+        const refHost = metadata.isArray ? { items: { $ref } } : { allOf: [{$ref}] };
         const paramObject = Object.assign(Object.assign({}, _schemaObject), refHost);
-        const pathsToOmit = ['enum', 'enumName', ...additionalParams];
+        const pathsToOmit = ['enum', 'enumName'];
         if (!metadata.isArray) {
             pathsToOmit.push('type');
         }

This change will wrap the $ref in an allOf as previously suggested and retain properties like description, deprecated and default as expected.

Unfortunately there's no way of documenting the enum itself, so this code copies the description from the property to the enum schema definition. This is still the original behavior.

arabold avatar Oct 09 '24 16:10 arabold

I have same issue(https://github.com/nestjs/swagger/issues/3101). actually The declaration doesn't disappear, but you can find its default in other schema declared enumName.

0816i avatar Oct 14 '24 00:10 0816i

https://github.com/nestjs/swagger/pull/3123

kamilmysliwiec avatar Oct 24 '24 13:10 kamilmysliwiec