import type { MiddlewareHandler } from 'hono' import type { Equal, Expect } from 'hono/utils/types' import type { MiddlewareToHandlerType, OfHandlerType, RouteHandler } from '../src' import { OpenAPIHono, createRoute, z } from '../src' describe('supports async handler', () => { const route = createRoute({ method: 'get', path: '/users', responses: { 200: { content: { 'application/json': { schema: z.object({ id: z.string(), }), }, }, description: 'Retrieve the user', }, }, }) test('argument of openapi method', () => { const hono = new OpenAPIHono() hono.openapi(route, (c) => { return c.json({ id: '123', }) }) hono.openapi(route, async (c) => { return c.json({ id: '123', }) }) }) test('RouteHandler type', () => { const handler: RouteHandler = (c) => { return c.json({ id: '123', }) } const asyncHandler: RouteHandler = async (c) => { return c.json({ id: '123', }) } const hono = new OpenAPIHono() hono.openapi(route, handler) hono.openapi(route, asyncHandler) }) test('RouteHandler infers env type from middleware', () => { type CustomEnv = { Variables: { customKey: string } } const customMiddleware: MiddlewareHandler = (c, next) => { c.set('customKey', 'customValue') return next() } const routeWithMiddleware = createRoute({ method: 'get', path: '/users', middleware: [customMiddleware] as const, responses: { 200: { content: { 'application/json': { schema: z.object({ id: z.string(), }), }, }, description: 'Retrieve the user', }, }, }) const handler: RouteHandler = (c) => { return c.json({ id: c.get('customKey'), }) } const hono = new OpenAPIHono() hono.openapi(routeWithMiddleware, handler) }) test('RouteHandler infers complex objects from multiple middleware handlers', () => { // https://github.com/honojs/middleware/issues/847 type CustomEnv = { Variables: { session: { id: string; createdAt: Date } } } const setSessionMiddleware: MiddlewareHandler = (c, next) => { c.set('session', { id: '8e760fe8-f064-4929-b632-737f88213e57', createdAt: new Date() }) return next() } const validateSessionMiddleware: MiddlewareHandler = async (c, next) => { const session = c.get('session') if ((new Date().getTime() - session.createdAt.getTime()) / 1000 / 60 / 60 > 1) { return c.json({ message: 'Unauthorized' }, 401) } return await next() } type Example = MiddlewareToHandlerType< [typeof setSessionMiddleware, typeof validateSessionMiddleware] > // ensure the first defined env does not lose its type in multi-middleware handler type Verify = Expect< Equal< OfHandlerType['env'], { Variables: CustomEnv['Variables'] } > > }) test('Route accepts a response other than the response from c.json() and c.text()', () => { const route = createRoute({ method: 'get', path: '/html', responses: { 200: { content: { 'text/html': { schema: z.string(), }, }, description: 'Return HTML', }, }, }) const handler: RouteHandler = (c) => { return c.html('

Hello from html

') } const hono = new OpenAPIHono() hono.openapi(route, handler) }) test('handler should support default response for unspecified status codes', () => { const routeWithDefault = createRoute({ method: 'get', path: '/users', responses: { 200: { content: { 'application/json': { schema: z.object({ id: z.string() }), }, }, description: 'Success response', }, default: { content: { 'application/json': { schema: z.object({ error: z.string() }), }, }, description: 'Error response', }, }, }) const errorHandler: RouteHandler = (c) => { return c.json({ error: 'Server Error' }, 500) } const hono = new OpenAPIHono() hono.openapi(routeWithDefault, errorHandler) }) test('handler should respect explicitly defined status codes with default fallback', () => { const routeWithDefault = createRoute({ method: 'get', path: '/users', responses: { 200: { content: { 'application/json': { schema: z.object({ id: z.string() }), }, }, description: 'Success response', }, 404: { content: { 'application/json': { schema: z.object({ message: z.string() }), }, }, description: 'Not found response', }, default: { content: { 'application/json': { schema: z.object({ error: z.string() }), }, }, description: 'Error response', }, }, }) const successHandler: RouteHandler = (c) => { return c.json({ id: '123' }, 200) } const notFoundHandler: RouteHandler = (c) => { return c.json({ message: 'Not Found' }, 404) } const errorHandler: RouteHandler = (c) => { return c.json({ error: 'Server Error' }, 500) } const hono = new OpenAPIHono() hono.openapi(routeWithDefault, successHandler) hono.openapi(routeWithDefault, notFoundHandler) hono.openapi(routeWithDefault, errorHandler) }) })