The OpenAPIHono class extends Hono with OpenAPI registry integration, automatic request/response validation, and type-safe route handling.
Extended Hono instance that maintains an OpenAPI registry and provides validation-aware route registration.
/**
* Extended Hono class with OpenAPI support and Zod validation
* @template E - Environment type for context variables
* @template S - Schema type for type-safe routing
* @template BasePath - Base path string for the application
*/
class OpenAPIHono<
E extends Env = Env,
S extends Schema = {},
BasePath extends string = '/'
> extends Hono<E, S, BasePath> {
/** Registry for OpenAPI definitions, components, and schemas */
openAPIRegistry: OpenAPIRegistry;
/** Default validation error handler applied to all routes */
defaultHook?: Hook<any, E, any, any>;
/** Create new OpenAPIHono instance with optional configuration */
constructor(init?: HonoInit<E>);
}Usage Examples:
import { OpenAPIHono } from "@hono/zod-openapi";
// Basic instance
const app = new OpenAPIHono();
// With default error handling
const app = new OpenAPIHono({
defaultHook: (result, c) => {
if (!result.success) {
return c.json({
ok: false,
errors: result.error.issues,
}, 422);
}
},
});
// With Hono configuration
const app = new OpenAPIHono({
strict: false,
defaultHook: myErrorHandler,
});Register OpenAPI-aware routes with automatic validation and type safety.
/**
* Register an OpenAPI route with validation and type safety
* @param route - Route configuration created with createRoute()
* @param handler - Request handler function with inferred types
* @param hook - Optional validation error handler (overrides defaultHook)
* @returns OpenAPIHono instance for chaining
*/
openapi<R extends RouteConfig>(
route: R,
handler: RouteHandler<R>,
hook?: RouteHook<R>
): OpenAPIHono<E, S & ToSchema<R['method'], MergePath<BasePath, ConvertPathType<R['path']>>,
InputTypes<R>, RouteConfigToTypedResponse<R>>, BasePath>;Usage Examples:
import { createRoute, z } from "@hono/zod-openapi";
const route = createRoute({
method: 'post',
path: '/users',
request: {
body: {
content: {
'application/json': {
schema: z.object({
name: z.string(),
email: z.string().email(),
}),
},
},
},
},
responses: {
201: {
content: {
'application/json': {
schema: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
}),
},
},
description: 'User created successfully',
},
},
});
// Register route with handler
app.openapi(route, (c) => {
const { name, email } = c.req.valid('json'); // Fully typed
const newUser = { id: '123', name, email };
return c.json(newUser, 201); // Status code is validated
});
// With custom error handling
app.openapi(
route,
(c) => {
const data = c.req.valid('json');
return c.json({ id: '123', ...data }, 201);
},
(result, c) => {
if (!result.success) {
return c.json({ error: 'Validation failed' }, 400);
}
}
);Mount sub-applications while merging their OpenAPI registries.
/**
* Mount a sub-application and merge OpenAPI registries
* @param path - Mount path using Hono parameter syntax (:param)
* @param app - Sub-application to mount (preferably OpenAPIHono)
* @returns OpenAPIHono instance with merged schemas
*/
route<SubPath extends string, SubEnv extends Env, SubSchema extends Schema, SubBasePath extends string>(
path: SubPath,
app?: Hono<SubEnv, SubSchema, SubBasePath>
): OpenAPIHono<E, MergeSchemaPath<SubSchema, MergePath<BasePath, SubPath>> & S, BasePath>;Usage Examples:
// Create sub-applications
const usersApp = new OpenAPIHono();
const ordersApp = new OpenAPIHono();
// Mount with registry merging
app.route('/api/users', usersApp);
app.route('/api/orders', ordersApp);
// Mount with path parameters (use Hono syntax, not OpenAPI)
const bookActionsApp = new OpenAPIHono();
app.route('/books/:bookId', bookActionsApp); // ✅ Correct
// app.route('/books/{bookId}', bookActionsApp); // ❌ IncorrectCreate new instance with a base path prefix.
/**
* Create new OpenAPIHono instance with base path
* @param path - Base path to prefix all routes
* @returns New OpenAPIHono instance with updated base path
*/
basePath<SubPath extends string>(path: SubPath): OpenAPIHono<E, S, MergePath<BasePath, SubPath>>;Usage Examples:
const apiApp = app.basePath('/api/v1');
// Routes registered on apiApp will be prefixed with /api/v1
apiApp.openapi(userRoute, handler); // Accessible at /api/v1/users/** Configuration options for OpenAPIHono constructor */
type HonoInit<E extends Env> = ConstructorParameters<typeof Hono>[0] & OpenAPIHonoOptions<E>;
interface OpenAPIHonoOptions<E extends Env> {
/** Default validation error handler applied to all routes */
defaultHook?: Hook<any, E, any, any>;
}
/** Extended Zod object with OpenAPI metadata support */
declare const z: typeof import('zod') & {
ZodSchema: {
openapi(metadata: object): this;
};
};Extends Zod with OpenAPI metadata methods to enable schema documentation.
/**
* Extends Zod with OpenAPI metadata methods
* @param z - Zod import to extend with OpenAPI functionality
*/
function extendZodWithOpenApi(z: typeof import('zod')): void;Usage Examples:
import { extendZodWithOpenApi, z } from "@hono/zod-openapi";
// Now you can use OpenAPI metadata on Zod schemas
const UserSchema = z.object({
id: z.string().openapi({ example: '123' }),
name: z.string().openapi({ example: 'John Doe' }),
email: z.string().email().openapi({ example: 'john@example.com' }),
}).openapi('User');Creates a new OpenAPIHono instance with a base path prefix for all routes.
/**
* Create new instance with base path prefix
* @param path - Base path to prefix all routes with
* @returns New OpenAPIHono instance with base path
*/
basePath<SubPath extends string>(path: SubPath): OpenAPIHono<E, S, MergePath<BasePath, SubPath>>;Usage Examples:
import { OpenAPIHono } from "@hono/zod-openapi";
const app = new OpenAPIHono();
// Create API v1 instance with base path
const v1 = app.basePath('/api/v1');
// Routes registered on v1 will be prefixed with /api/v1
v1.openapi(userRoute, userHandler); // Available at /api/v1/users/{id}
v1.openapi(postRoute, postHandler); // Available at /api/v1/posts/{id}The OpenAPI registry is accessible for advanced usage including component registration and security setup.
// Access the registry
const registry = app.openAPIRegistry;
// Register custom components
app.openAPIRegistry.registerComponent('schemas', 'CustomSchema', mySchema);
// Register security schemes
app.openAPIRegistry.registerComponent('securitySchemes', 'Bearer', {
type: 'http',
scheme: 'bearer',
});
app.openAPIRegistry.registerComponent('securitySchemes', 'ApiKey', {
type: 'apiKey',
in: 'header',
name: 'X-API-Key',
});Configure authentication and authorization for your API routes.
Usage Examples:
// 1. Register security schemes
app.openAPIRegistry.registerComponent('securitySchemes', 'Bearer', {
type: 'http',
scheme: 'bearer',
});
// 2. Apply security to routes
const secureRoute = createRoute({
method: 'get',
path: '/protected',
security: [{ Bearer: [] }], // Apply Bearer auth
responses: {
200: {
content: { 'application/json': { schema: z.object({}) } },
description: 'Protected resource',
},
401: {
description: 'Unauthorized',
},
},
});
// 3. Use lowercase header validation
const AuthHeadersSchema = z.object({
authorization: z.string().openapi({
example: 'Bearer SECRET',
}),
});
const routeWithHeaders = createRoute({
method: 'get',
path: '/with-auth',
request: {
headers: AuthHeadersSchema,
},
responses: {
200: {
content: { 'application/json': { schema: z.object({}) } },
description: 'Success',
},
},
});