asteasolutions / zod-to-openapi

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

Named for openapi schema extension doesn't extracts into components.schema #273

Open artsiommiksiuk opened 3 days ago

artsiommiksiuk commented 3 days ago
export const PublicUserSchema = z.object({
    id: z.string().uuid(),
    avatarUrl: z.string().optional(),
    name: z.string(),
    email: z.string(),
}).openapi("User");

export const AgentUserStateSchema = z.enum(["active", "inactive"]).openapi("UserState");
export const AgentUserSchema = PublicUserSchema.extend({
    state: AgentUserStateSchema,
}).openapi("User");

export getUser = (): RouteConfig => ({
        summary: "Get user",
        tags,
        method: "get",
        operationId: "getUser",
        path: "/users/{userId}",
        request: {
            params: z.object({
                userId: UserIdPathParameter,
            })
        },
        responses: {
            "200": {
                description,
                content: {
                     "application/json": {
                           schema: AgentUserSchema,
                     }
                }
           }
    })

This leads to that schema being inlined into request as:

/users/{userId}:
    get:
      summary: Get user
      tags:
        - user
      operationId: getUser
      parameters:
        - schema:
            $ref: "#/components/schemas/UserId"
          required: true
          in: path
          name: userId
      responses:
        "200":
          description: User
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/User"
                  - allOf:
                      - $ref: "#/components/schemas/User"
                      - type: object
                        properties:
                          state:
                            $ref: "#/components/schemas/UserState"
                        required:
                          - state

I'd expect it to be as well extracted to components.schema.

So, I'd like it to be extracted into components.schema part.

As another possibility I'm looking for, is to avoid allOf usage for extension, and have a hard merged objects. Is it possible?

artsiommiksiuk commented 3 days ago

Okay, seems like I figured answer to my question.

if I do the hard copy, instead of .extend(),

export const AgentUserSchema = z.object({
    ...PublicUserSchema.shape,
    state: AgentUserStateSchema,
}).openapi("User");

Then it produces hard type (without anyOf). Makes sense.

Still, with the inline part, I think it is a bug of itself.