asteasolutions / zod-to-openapi

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

It will build strange "allOf" schema when referenceObject has discription. #193

Open wiz-tajima opened 7 months ago

wiz-tajima commented 7 months ago

I often assign a schema with "shape", but sometimes it will make building wrong allOf schema. For example, I've written this zod schema:

const FooSchema = z.object({
 grade: z.nativeEnum(SomeEnum)
})

const BarSchema = z.object({
 parent_foo_grade: FooSchema.shape.grade.describe("parent's grade")
})

and registry this. Then, it will build this strange allOf:

BarSchema:
      type: object
      properties:
        parent_foo_grade:
          allOf:
            - $ref: "#/components/schemas/GradeSchema"
            - description: parent's grade
      required:
        - parent_foo_grade

This isn't correct OpenApi schema, so this makes wrong when pass for a library: orval.

I've researched the matter, and I found dubious behavior on function named "generateSimpleSchema". generateSimpleSchema has this code:

 const newMetadata = (0, lodash_1.omitBy)(this.buildSchemaMetadata((_a = metadata === null || metadata === void 0 ? void 0 : metadata.metadata) !== null && _a !== void 0 ? _a : {}), (value, key) => value === undefined || (0, lodash_1.objectEquals)(value, schemaRef[key]));
        // Do not calculate schema metadata overrides if type is provided in .openapi
        // https://github.com/asteasolutions/zod-to-openapi/pull/52/files/8ff707fe06e222bc573ed46cf654af8ee0b0786d#r996430801
        if (newMetadata.type) {
            return {
                allOf: [referenceObject, newMetadata],
            };
        }

And I found the variable "newMetadata", can be assigned description.

I think description mustn't be included in allOf. How can I do to resolve this problem?

AGalabov commented 7 months ago

@wiz-tajima thank you for reporting. I'd definitely have to investigate this to give a full answer since this is a generic logic that we use everywhere across the "generator". I'd have to figure out if description is the only invalid field or if there are any. And what should be the correct way to handle those (if it is incorrect to start with)