diff --git a/.changeset/zod-openapi-define-route-middleware-env.md b/.changeset/zod-openapi-define-route-middleware-env.md new file mode 100644 index 000000000..4740ff842 --- /dev/null +++ b/.changeset/zod-openapi-define-route-middleware-env.md @@ -0,0 +1,5 @@ +--- +'@hono/zod-openapi': patch +--- + +`defineOpenAPIRoute` now infers handler `Env` (Variables/Bindings) from the route's `middleware`, matching `OpenAPIHono.openapi()` behavior. diff --git a/packages/zod-openapi/src/handler.test-d.ts b/packages/zod-openapi/src/handler.test-d.ts index ba3dfd518..d17c45d51 100644 --- a/packages/zod-openapi/src/handler.test-d.ts +++ b/packages/zod-openapi/src/handler.test-d.ts @@ -1,7 +1,7 @@ import type { MiddlewareHandler } from 'hono' import type { Equal, Expect } from 'hono/utils/types' import type { MiddlewareToHandlerType, OfHandlerType, RouteHandler } from '.' -import { OpenAPIHono, createRoute, z } from '.' +import { OpenAPIHono, createRoute, defineOpenAPIRoute, z } from '.' describe('supports async handler', () => { const route = createRoute({ @@ -229,3 +229,41 @@ describe('supports async handler', () => { hono.openapi(routeWithDefault, errorHandler) }) }) + +describe('defineOpenAPIRoute', () => { + test('handler infers env type from route middleware', () => { + // https://github.com/honojs/middleware/issues/1879 + type Identity = { id: string } + type CustomEnv = { Variables: { identity: Identity } } + + const requireIdentity: MiddlewareHandler = async (c, next) => { + c.set('identity', { id: '123' }) + await next() + } + + const definition = defineOpenAPIRoute({ + route: createRoute({ + method: 'get', + path: '/me', + middleware: [requireIdentity] as const, + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ id: z.string() }), + }, + }, + description: 'ok', + }, + }, + }), + handler: (c) => { + type IdentityType = typeof c.var.identity + type Verify = Expect> + return c.json({ id: c.var.identity.id }, 200) + }, + }) + + new OpenAPIHono().openapiRoutes([definition]) + }) +}) diff --git a/packages/zod-openapi/src/index.ts b/packages/zod-openapi/src/index.ts index cfa40e54f..14cad7b18 100644 --- a/packages/zod-openapi/src/index.ts +++ b/packages/zod-openapi/src/index.ts @@ -404,9 +404,16 @@ type ComputeInput = InputTypeParam & InputTypeForm & InputTypeJson +// Helper: Merge env with route middleware env (if any) +type EnvFromRoute = R['middleware'] extends + | MiddlewareHandler[] + | MiddlewareHandler + ? RouteMiddlewareParams['env'] & E + : E + // Helper: Calculate the expected Handler type for a specific RouteConfig type HandlerFromRoute = Handler< - E, + EnvFromRoute, ConvertPathType, ComputeInput, R extends { @@ -425,7 +432,7 @@ type HandlerFromRoute = Handler< type HookFromRoute = | Hook< ComputeInput, - E, + EnvFromRoute, ConvertPathType, R extends { responses: {