asteasolutions / zod-to-openapi

A library that generates OpenAPI (Swagger) docs from Zod schemas
MIT License
919 stars 57 forks source link

Enum components are being generated as nullable when the property holding it is nullable #258

Open renke0 opened 2 weeks ago

renke0 commented 2 weeks ago

Description

I have the following scenario:

const Brand = z.enum(['Ford', 'Toyota', 'Tesla']).openapi('Brand');

const Car = z
    .object({
        brand: Brand.nullable(),
        model: z.string(),
    })
    .openapi('Car');

Expected result

I expected the property Car.brand to be a nullable Brand

components:
  schemas:
    Brand:
      type: string
      enum:
        - Ford
        - Toyota
        - Tesla
    Car:
      type: object
      properties:
        brand:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/Brand'
        model:
          type: string

Actual result

The spec generated declares Brand as nullable, instead of making the property Car.brand nullable

components:
  schemas:
    Brand:
      type:
        - string
        - 'null'
      enum:
        - Ford
        - Toyota
        - Tesla
    Car:
      type: object
      properties:
        brand:
          $ref: '#/components/schemas/Brand'
        model:
          type: string

More info

I understand the rationale behind the way this was generated. The problem is that Brand could be reusable, and in some places it might not be nullable. Is there a workaround this?

AGalabov commented 2 days ago

@renke0 I can see the problem. If you pass Brand before Car in the OpenApiGeneratorV3 constructor's array of definitions everything works fine. But if you switch their order or simply do not pass Brand at all then what you've described happens.

I am not sure how easy it would be for us to fix this and when we will have the time for it. In the mean time - you can make sure to pass it in order as a workaround.