or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-openapi.mdindex.mdopenapi-generation.mdroute-creation.mdvalidation-error-handling.md
tile.json

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