asteasolutions / zod-to-openapi

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

Improve/expand Record in generated Open API file #211

Closed Couto closed 7 months ago

Couto commented 7 months ago

I'm not sure if this is working as intended, but I will explain my problem and my expectations:

We're building a quizz where users have to associate countries with continents, the answers might contain wrong associations ofc.

const Continents = z
  .enum(['EUROPE', 'AFRICA', 'NORTH_AMERICA'])
  .describe('List of Continents');

const Countries = z
  .enum(['USA', 'CAN', 'GBR'])
  .describe('Country ISO code (Alpha-3)');

export const Geography = z
  .record(Continents, z.object({
    countries: Countries.array(),
  }))
  .openapi('Geography', {
    example: {
      EUROPE: { countries: ['GBR'] },
      NORTH_AMERICA: { countries: ['USA', 'CAN'] },
    },
  });

As far as Zod is concerned, this works fine. The problem is the generated Open API file, which could be a bit better (imho). As is, right now, the generated file contains the following:

  schemas:
    Geography:
      type: object
      additionalProperties:
        type: object
        properties:
          countries:
            type: array
            items:
              type: string
              enum:
                - USA
                - CAN
                - GBR
              description: Country ISO code (Alpha-3)
            description: Country ISO code (Alpha-3)
        required:
          - countries
      example:
        EUROPE:
          countries:
            - GBR
        NORTH_AMERICA:
          countries:
            - USA
            - CAN

However, my expectation of the final Open API file was something like:

    Geography:
      type: object
      properties:
        EUROPE:
          type: object
          properties:
            countries:
              type: array
              items:
                type: string
                enum: &a1
                  - USA
                  - CAN
                  - GBR
                description: Country ISO code (Alpha-3)
              description: Country ISO code (Alpha-3)
          required:
            - countries
        AFRICA:
          type: object
          properties:
            countries:
              type: array
              items:
                type: string
                enum: *a1
                description: Country ISO code (Alpha-3)
              description: Country ISO code (Alpha-3)
          required:
            - countries
        NORTH_AMERICA:
          type: object
          properties:
            countries:
              type: array
              items:
                type: string
                enum: *a1
                description: Country ISO code (Alpha-3)
              description: Country ISO code (Alpha-3)
          required:
            - countries
      example:
        EUROPE:
          countries:
            - GBR
        NORTH_AMERICA:
          countries:
            - USA
            - CAN

Is my expectation wrong here? I know it's possible to use the z.object to achieve the final example, and it works fine with a small number of keys, but codewise the z.enum should work? Is this something that can be improved?

AGalabov commented 7 months ago

@Couto thank you for bringing this up.

To be completely honest - we've never into the option of providing keys to the record. I would have to check how the schema looks like within zod and come back to you with an answer of whether or not it is possible

AGalabov commented 7 months ago

Hey @Couto - I've just opened a PR with pretty much your example in the tests - feel free to take a look. Hopefully we should be able to review, merge and publish it soon.

AGalabov commented 7 months ago

@Couto - released as part of v6.4.0

Couto commented 7 months ago

Thank you so much for this, and the quick response.