CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hono--zod-openapi

Extended Hono class that integrates OpenAPI specification generation with Zod schema validation for type-safe REST APIs.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

core-openapi.mddocs/

Core OpenAPI Integration

The OpenAPIHono class extends Hono with OpenAPI registry integration, automatic request/response validation, and type-safe route handling.

Capabilities

OpenAPIHono Class

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

Route Registration

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

Application Mounting

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); // ❌ Incorrect

Base Path Configuration

Create 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 Types

/** 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;
  };
};

Zod OpenAPI Extension

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

Base Path Configuration

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}

Registry Access

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

Security Setup

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

docs

core-openapi.md

index.md

openapi-generation.md

route-creation.md

validation-error-handling.md

tile.json