nestjs / swagger

OpenAPI (Swagger) module for Nest framework (node.js) :earth_americas:

Home Page:https://nestjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom `type` is not retained as type, but rewritten as `allOf: - $ref: ...` breaking `nullable: true` spec in `@ApiProperty`

gregoryorton-ws opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Custom type is not retained as type, but rewritten as allOf: - $ref: ... breaking nullable: true spec in @ApiProperty

In @ApiProperty when using something like:

@ApiProperty({ nullable: true, type: MyCustomDto })
readonly myVar: MyCustomDto | null;
...

the rendered openapi.yaml is like:

myVar:
  nullable: true
  allOf:
     - $ref: "#/components/schemas/MyCustomDto"

tools like Redoc.ly then start to throw errors:

image

Minimum reproduction code

https://nothing.com

Steps to reproduce

see above

Expected behavior

myVar:
  type: object
  properties:
    id:
      type: integer

Package version

7.3.0

NestJS version

10.3.3

Node.js version

20

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

maybe related: #2645
maybe related: #2646

Would you like to create a PR for this issue?

Sure, but I don't know what the solution would be here -

what should the value of type be? Would we need to put the custom DTO into a schemas and then reference it?

One solution looks like:

myVar:
  nullable: true
  allOf:
    - $ref: "#/components/schemas/MyCustomDto"
    - type: object

I will test with redoc.ly to see if it's acceptable. If it is, then I think we can just add this type to the output for the custom type.

The only think redoc.ly will accept is:

myVar:
  nullable: true
  type: object
  allOf:
    - $ref: "#/components/schemas/MyCustomDto"

so it seems like an easy fix

Here is the source of our woes:

const keysToRemove = ['type', 'isArray', 'required'];
const validMetadataObject = omit(metadata, keysToRemove);
const extraMetadataKeys = Object.keys(validMetadataObject);
if (extraMetadataKeys.length > 0) {
return {
name: metadata.name || key,
required: metadata.required,
...validMetadataObject,
allOf: [{ $ref }]
} as SchemaObjectMetadata;
}

Extra keys that are not in the set of ['type', 'isArray', 'required'] will result in an allOf instead of a direct $ref. In this case (and #2645), the key is nullable. In my case, it's name.

The list of supported keys needs to be expanded, or removed altogether. I'm not sure which one as I haven't read the OpenAPI spec to any level of detail.