Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zod OpenAPI Hono - .catch make all the openapi doc resolve to an empty JSON #865

Open
StevenSermeus opened this issue Dec 2, 2024 · 0 comments

Comments

@StevenSermeus
Copy link

StevenSermeus commented Dec 2, 2024

Issue description

When working with the middleware and adding a catch handler to a route's description, I observed that the OpenAPI documentation fails to generate properly and results in a 500 Internal Server Error. Below is the relevant code snippet that causes the issue.

Steps to Reproduce

  1. Use the @hono/zod-openapi library to define an API route.
  2. Add a catch handler to the dialogs array schema in the request body, as shown in the code below.
  3. Attempt to generate or interact with the OpenAPI documentation for the route.
  4. Observe that the OpenAPI middleware fails with a 500 Internal Server Error.
// Working file with all my doc
export const storyStepRoute = createRoute({
  method: 'post',
  description: 'Create a new story step with dialogs',
  tags: ['StoryStep'],
  path: '/',
  security: [],
  request: {
    body: {
      content: {
        'multipart/form-data': {
          schema: z.object({
            title: z.string().max(255).min(2),
            image: FileRequestSchema,
            dialogs: z.array(
              z.object({
                title: z.string().max(255).min(2),
                content: z.string().max(10000).min(2),
                order: z.number().int().nonnegative(),
              })
            ),
          }),
        },
      },
    },
  },
  responses: {
    ...protectedRouteResponse,
    ...authorizedResponse,
    500: {
      description: 'Internal Server Error',
      content: {
        'application/json': {
          schema: z.object({
            message: z.string(),
          }),
        },
      },
    },
    201: {
      description: 'Story step information',
      content: {
        'application/json': {
          schema: z.object({
            id: z.string(),
            title: z.string(),
            imageUrl: z.string(),
            dialogs: z.array(
              z.object({
                id: z.string(),
                title: z.string(),
                content: z.string(),
                order: z.number(),
                createdAt: z.date(),
                updatedAt: z.date(),
              })
            ),
            createdAt: z.date(),
            updatedAt: z.date(),
          }),
        },
      },
    },
  },
});
import { OpenAPIHono, createRoute } from '@hono/zod-openapi';

import { FileRequestSchema } from '@/server/libs/openApi';


export const storyStepRoute = createRoute({
  method: 'post',
  description: 'Create a new story step with dialogs',
  tags: ['StoryStep'],
  path: '/',
  security: [],
  request: {
    body: {
      content: {
        'multipart/form-data': {
          schema: z.object({
            title: z.string().max(255).min(2),
            image: FileRequestSchema,
            dialogs: z
              .array(
                z.object({
                  title: z.string().max(255).min(2),
                  content: z.string().max(10000).min(2),
                  order: z.number().int().nonnegative(),
                })
              )
              .catch(ctx => { // This kill all the open api doc
                if (typeof ctx.input !== 'string') throw new Error('Invalid input type');
                try {
                  return JSON.parse(ctx.input);
                } catch (error) {
                  throw new Error('Invalid JSON input');
                }
              }),
          }),
        },
      },
    },
  },
  responses: {
    500: {
      description: 'Internal Server Error',
      content: {
        'application/json': {
          schema: z.object({
            message: z.string(),
          }),
        },
      },
    },
    201: {
      description: 'Story step information',
      content: {
        'application/json': {
          schema: z.object({
            id: z.string(),
            title: z.string(),
            imageUrl: z.string(),
            dialogs: z.array(
              z.object({
                id: z.string(),
                title: z.string(),
                content: z.string(),
                order: z.number(),
                createdAt: z.date(),
                updatedAt: z.date(),
              })
            ),
            createdAt: z.date(),
            updatedAt: z.date(),
          }),
        },
      },
    },
  },
});

Observed Behavior

  • Adding the .catch() block to the dialogs array schema breaks the OpenAPI middleware functionality.
  • The documentation generation fails entirely.
  • The API server responds with a 500 Internal Server Error.

Expected Behavior

  • The .catch() block should not interfere with OpenAPI documentation generation.
  • The OpenAPI middleware should gracefully handle schemas with .catch() handlers or provide a meaningful error message to aid debugging.

Environment Details

  • Library Version: @hono/zod-openapi:0.16.0
  • Node.js Version: v20.14.0
  • Zod Version: 3.23.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant