Skip to content

Conversation

@soartec-lab
Copy link
Member

Summary

fix zod schema generation for OpenAPI schemas with oneOf/anyOf and common properties

Changes

Combine oneOf/anyOf with common properties using .and()

This fix handles OpenAPI schemas like:

Pet:
  oneOf:
    - oneOf:
        - $ref: '#/components/schemas/Labradoodle'
        - $ref: '#/components/schemas/Dachshund'
      properties:
        barksPerMinute:
          type: integer
        type:
          type: string
          enum: [dog]
    - properties:
        petsRequested:
          type: integer
        type:
          type: string
          enum: [cat]
  properties:
    '@id':
      type: string
    id:
      type: integer
    name:
      type: string
    tag:
      type: string
    email:
      type: string
      format: email
    callingCode:
      $ref: '#/components/schemas/PetCallingCode'
    country:
      $ref: '#/components/schemas/PetCountry'
  required:
    - id
    - name

Before

Common properties were missing:

export const Pet = zod.union([zod.union([zod.object({
  "cuteness": zod.number()
}),zod.object({
  "length": zod.number()
})]),zod.object({
  "petsRequested": zod.number().optional(),
  "type": zod.enum(['cat'])
})])

After

Common properties are correctly combined using .and():

export const Pet = zod.union([zod.union([zod.object({
  "cuteness": zod.number()
}),zod.object({
  "length": zod.number()
})]).and(zod.object({
  "barksPerMinute": zod.number().optional(),
  "type": zod.enum(['dog'])
})),zod.object({
  "petsRequested": zod.number().optional(),
  "type": zod.enum(['cat'])
})]).and(zod.object({
  "@id": zod.string().optional(),
  "id": zod.number(),
  "name": zod.string(),
  "tag": zod.string().optional(),
  "email": zod.string().email().optional(),
  "callingCode": zod.enum(['+33', '+420', '+33']).optional(),
  "country": zod.enum(['People\'s Republic of China', 'Uruguay']).optional()
}))

@soartec-lab soartec-lab added this to the 8.0.0 milestone Dec 23, 2025
@soartec-lab soartec-lab added bug Something isn't working zod Zod related issue labels Dec 23, 2025
@soartec-lab soartec-lab marked this pull request as ready for review December 23, 2025 00:52
Copilot AI review requested due to automatic review settings December 23, 2025 00:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the Zod schema generation for OpenAPI schemas that combine oneOf/anyOf with common properties. Previously, common properties defined at the parent level were omitted from the generated schemas. The fix uses Zod's .and() method to properly merge the union schemas with the common properties.

Key changes:

  • Modified the logic in generateZodValidationSchemaDefinition to handle common properties for oneOf/anyOf schemas
  • Generated schemas now use .and() to combine unions with common properties instead of ignoring them

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
packages/zod/src/index.ts Updated schema generation logic to handle oneOf/anyOf with common properties using .and()
samples/swr-with-zod/src/gen/endpoints/pets/pets.zod.ts Regenerated schemas demonstrating the fix with common properties now included
samples/hono/hono-with-zod/src/petstore.zod.ts Regenerated schemas demonstrating the fix with common properties now included

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Suggested change
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
callingCode: zod.enum(['+33', '+420']).optional(),

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
name: zod.string(),
tag: zod.string().optional(),
email: zod.string().email().optional(),
callingCode: zod.enum(['+33', '+420', '+33']).optional(),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingCode enum contains duplicate values ('+33' appears twice). This duplication is unnecessary and should be removed to maintain a clean enum definition.

Copilot uses AI. Check for mistakes.
@melloware melloware merged commit 4b17788 into orval-labs:master Dec 23, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working zod Zod related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants