Extended Hono class that integrates OpenAPI specification generation with Zod schema validation for type-safe REST APIs.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Hono Zod OpenAPI is an extended Hono class that integrates OpenAPI specification generation with Zod schema validation. It enables developers to build type-safe REST APIs with automatic OpenAPI documentation generation, combining Hono's lightweight web framework with Zod's runtime type validation.
npm install hono zod @hono/zod-openapiimport {
OpenAPIHono,
createRoute,
z,
extendZodWithOpenApi,
type RouteConfig,
type Hook,
type OpenAPIHonoOptions
} from "@hono/zod-openapi";For CommonJS:
const {
OpenAPIHono,
createRoute,
z,
extendZodWithOpenApi
} = require("@hono/zod-openapi");For advanced type usage:
import type {
RouteHandler,
RouteHook,
RouteConfigToTypedResponse,
DeepSimplify,
OfHandlerType,
OpenAPIObjectConfigure,
OpenAPIGeneratorConfigure
} from "@hono/zod-openapi";import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
// Define schemas with OpenAPI metadata
const ParamsSchema = z.object({
id: z.string().min(3).openapi({
param: { name: 'id', in: 'path' },
example: '1212121',
}),
});
const UserSchema = z.object({
id: z.string().openapi({ example: '123' }),
name: z.string().openapi({ example: 'John Doe' }),
age: z.number().openapi({ example: 42 }),
}).openapi('User');
// Create route configuration
const route = createRoute({
method: 'get',
path: '/users/{id}',
request: { params: ParamsSchema },
responses: {
200: {
content: {
'application/json': { schema: UserSchema },
},
description: 'Retrieve the user',
},
},
});
// Set up the app and register route
const app = new OpenAPIHono();
app.openapi(route, (c) => {
const { id } = c.req.valid('param');
return c.json({
id,
age: 20,
name: 'Ultra-man',
}, 200);
});
// Generate OpenAPI documentation endpoint
app.doc('/doc', {
openapi: '3.0.0',
info: {
version: '1.0.0',
title: 'My API',
},
});Hono Zod OpenAPI is built around several key components:
createRoute with Zod schemasThe main OpenAPIHono class and basic route registration functionality. Provides the foundation for building type-safe APIs with automatic validation.
class OpenAPIHono<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>
extends Hono<E, S, BasePath> {
openAPIRegistry: OpenAPIRegistry;
defaultHook?: Hook<any, E, any, any>;
constructor(init?: HonoInit<E>);
openapi<R extends RouteConfig>(
route: R,
handler: RouteHandler<R>,
hook?: RouteHook<R>
): OpenAPIHono;
}Route definition system using createRoute function with comprehensive configuration options for request validation, response schemas, and middleware.
function createRoute<P extends string, R extends Omit<RouteConfig, 'path'> & { path: P }>(
routeConfig: R
): R & { getRoutingPath(): RoutingPath<R['path']> };
interface RouteConfig extends RouteConfigBase {
middleware?: MiddlewareHandler | MiddlewareHandler[];
hide?: boolean;
}Route Creation & Configuration
Validation hooks and error handling patterns for processing request validation results and generating appropriate responses.
type Hook<T, E extends Env, P extends string, R> = (
result: { target: keyof ValidationTargets } & (
| { success: true; data: T }
| { success: false; error: ZodError }
),
c: Context<E, P>
) => R;
interface OpenAPIHonoOptions<E extends Env> {
defaultHook?: Hook<any, E, any, any>;
}OpenAPI document generation methods supporting both OpenAPI 3.0 and 3.1 specifications with configurable generation options.
getOpenAPIDocument(
objectConfig: OpenAPIObjectConfig,
generatorConfig?: OpenAPIGeneratorOptions
): OpenAPIObject;
getOpenAPI31Document(
objectConfig: OpenAPIObjectConfig,
generatorConfig?: OpenAPIGeneratorOptions
): OpenAPIV31Object;
doc<P extends string>(
path: P,
configureObject: OpenAPIObjectConfigure<E, P>,
configureGenerator?: OpenAPIGeneratorConfigure<E, P>
): OpenAPIHono;interface RouteConfig extends RouteConfigBase {
middleware?: MiddlewareHandler | MiddlewareHandler[];
hide?: boolean;
}
/** Extracts union of TypedResponse types from route configuration responses */
type RouteConfigToTypedResponse<R extends RouteConfig> = TypedResponse<
InferredResponseContent<R>,
InferredStatusCodes<R>,
InferredResponseFormat<R>
>;
type RouteHandler<R extends RouteConfig> = Handler<
RouteConfigToEnv<R>,
ConvertPathType<R['path']>,
InputTypeParam<R> & InputTypeQuery<R> & InputTypeHeader<R> &
InputTypeCookie<R> & InputTypeForm<R> & InputTypeJson<R>,
MaybePromise<RouteConfigToTypedResponse<R>> | MaybePromise<Response>
>;
type RouteHook<R extends RouteConfig> = Hook<
InputTypeParam<R> & InputTypeQuery<R> & InputTypeHeader<R> &
InputTypeCookie<R> & InputTypeForm<R> & InputTypeJson<R>,
RouteConfigToEnv<R>,
ConvertPathType<R['path']>,
RouteConfigToTypedResponse<R> | Response | Promise<Response> | void | Promise<void>
>;
type OpenAPIObjectConfigure<E extends Env, P extends string> =
| OpenAPIObjectConfig
| ((context: Context<E, P>) => OpenAPIObjectConfig);
type OpenAPIGeneratorConfigure<E extends Env, P extends string> =
| OpenAPIGeneratorOptions
| ((context: Context<E, P>) => OpenAPIGeneratorOptions);
/** Recursive type simplification utility */
type DeepSimplify<T> = {
[KeyType in keyof T]: T[KeyType] extends Record<string, unknown>
? DeepSimplify<T[KeyType]>
: T[KeyType];
} & {};
/** Extract environment, path, and input types from middleware handler */
type OfHandlerType<T extends MiddlewareHandler> =
T extends MiddlewareHandler<infer E, infer P, infer I>
? {
env: E;
path: P;
input: I;
}
: never;
/** Compose multiple middleware handlers into single handler type */
type MiddlewareToHandlerType<M extends MiddlewareHandler<any, any, any>[]> =
M extends [infer First, infer Second, ...infer Rest]
? First extends MiddlewareHandler<any, any, any>
? Second extends MiddlewareHandler<any, any, any>
? Rest extends MiddlewareHandler<any, any, any>[]
? MiddlewareToHandlerType<[
MiddlewareHandler<
DeepSimplify<OfHandlerType<First>['env'] & OfHandlerType<Second>['env']>,
OfHandlerType<First>['path'],
OfHandlerType<First>['input']
>,
...Rest
]>
: never
: never
: never
: M extends [infer Last]
? Last
: MiddlewareHandler<Env>;
/** Extract middleware parameters from route configuration */
type RouteMiddlewareParams<R extends RouteConfig> = OfHandlerType<
MiddlewareToHandlerType<AsArray<R['middleware']>>
>;
/** Extract environment type from route configuration */
type RouteConfigToEnv<R extends RouteConfig> =
RouteMiddlewareParams<R> extends never
? Env
: RouteMiddlewareParams<R>['env'];
/** Helper type to convert T | T[] | undefined into T[] */
type AsArray<T> = T extends undefined
? []
: T extends any[]
? T
: [T];