middleware icon indicating copy to clipboard operation
middleware copied to clipboard

[zod-openapi] Wrong return type from `use`

Open hpohlmeyer opened this issue 1 year ago • 3 comments

When using the chaining approach needed for Hono RPC with a middleware, OpenApiHono specific methods do not exist on the chain anymore after using use, because use returns Hono instead of OpenApiHono.

const app = new OpenAPIHono()
//     ^? const app: any
  .use("/*", cors())
  .route("/", orgsRouter)
  .route("/", sitesRouter)
  .doc("/doc", { // Property 'doc' does not exist on type 'Hono<{}, { "/*": {}; } | MergeSchemaPath<{ "/orgs": { $get: { input: {}; output: { orgs: { name: string; id: string; createdAt: string; updatedAt: string; }[]; }; outputFormat: "json" | "text"; status: 200; }; }; } & { "/orgs/:orgId": { ...; }; }, "/"> | MergeSchemaPath<...>, "/">'
    openapi: "3.0.0",
    info: { … },
  })
  .get("/ui", swaggerUI({ url: "/doc" }));

Ideally these kind of issues would be solved by returning this from the base hono class, but we would need to pass on the modified generics to this, which is not supported by typescript yet. That means every Hono method should be repesented in the OpenAPIHono class definition as well, but with OpenAPIHono as the return type. To fix this issue it looks like we need to add the use method with the proper return type to the OpenAPIHono type declaration.

hpohlmeyer avatar Nov 25 '24 10:11 hpohlmeyer

Hi @hpohlmeyer

That's right, OpenAPIHono does not provide that feature due to the limitations of Hono's type definitions. It will have to be redefined in OpenAPIHono.

yusukebe avatar Nov 26 '24 14:11 yusukebe

@hpohlmeyer the way that i do it is i separate the router and server part:

export const mainRouter = new OpenAPIHono()
  .basePath('/api/v1')
  .route('/auth', authRouter)
  .doc('/doc', {})

export type AppType = typeof mainRouter;
const app = new OpenAPIHono()
  .use(
    '*',
    cors({ origin: [process.env.DASHBOARD_URL], credentials: true })
  )
  .route('/', mainRouter);

const port = getPortFromURL(process.env.API_URL, 3000);

serve({ fetch: app.fetch, port }).on('listening', () => {
  console.log(`>>> API running on ::${port}`);
});

Hope that helps!

askorupskyy avatar Nov 26 '24 17:11 askorupskyy

Any updates on this? It's an annoying bug because it makes using middleware impossible without getting type errors if they are chained in the usual way. Even this example from the readme:

import { prettyJSON } from 'hono/pretty-json'
import { cache } from 'hono/cache'

app.use(route.getRoutingPath(), prettyJSON(), cache({ cacheName: 'my-cache' }))
app.openapi(route, handler)

Is not correct as this creates a type error.

I have not tested using the middleware property on the createRoute object but even then I don't think that would be a solution because I assume that middleware would be tied to the single route and not to a collection of routes.

I've added an issue to report this in more detail: #930

Rick-Phoenix avatar Jan 08 '25 15:01 Rick-Phoenix