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
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',
},
},
});