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

route-creation.mddocs/

Route Creation & Configuration

Route definition system using the createRoute function with comprehensive configuration options for request validation, response schemas, middleware, and OpenAPI metadata.

Capabilities

Route Creation Function

Creates a type-safe route configuration object with OpenAPI metadata and validation schemas.

/**
 * Creates a route configuration object with routing path utility
 * @param routeConfig - Route configuration with path, method, request/response schemas
 * @returns Enhanced route config with getRoutingPath() method
 */
function createRoute<P extends string, R extends Omit<RouteConfig, 'path'> & { path: P }>(
  routeConfig: R
): R & {
  getRoutingPath(): RoutingPath<R['path']>;
};

Usage Examples:

import { createRoute, z } from "@hono/zod-openapi";

// Basic GET route with path parameters
const getUserRoute = createRoute({
  method: 'get',
  path: '/users/{id}',
  request: {
    params: z.object({
      id: z.string().openapi({
        param: { name: 'id', in: 'path' },
        example: '123',
      }),
    }),
  },
  responses: {
    200: {
      content: {
        'application/json': {
          schema: z.object({
            id: z.string(),
            name: z.string(),
            email: z.string(),
          }).openapi('User'),
        },
      },
      description: 'User details',
    },
    404: {
      content: {
        'application/json': {
          schema: z.object({
            error: z.string(),
          }),
        },
      },
      description: 'User not found',
    },
  },
});

// POST route with JSON body validation
const createUserRoute = createRoute({
  method: 'post',
  path: '/users',
  request: {
    body: {
      content: {
        'application/json': {
          schema: z.object({
            name: z.string().min(1),
            email: z.string().email(),
            age: z.number().int().min(0).optional(),
          }),
        },
      },
    },
  },
  responses: {
    201: {
      content: {
        'application/json': {
          schema: z.object({
            id: z.string(),
            name: z.string(),
            email: z.string(),
            age: z.number().optional(),
          }),
        },
      },
      description: 'User created successfully',
    },
  },
});

// Use routing path utility
const path = getUserRoute.getRoutingPath(); // "/users/:id" (Hono format)

Route Configuration Interface

Complete route configuration structure with all available options.

/**
 * Route configuration extending OpenAPI RouteConfigBase
 */
interface RouteConfig extends RouteConfigBase {
  /** Route-specific middleware handlers */
  middleware?: MiddlewareHandler | MiddlewareHandler[];
  /** Hide route from OpenAPI documentation */
  hide?: boolean;
}

/**
 * Base route configuration from @asteasolutions/zod-to-openapi
 */
interface RouteConfigBase {
  /** HTTP method */
  method: 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options';
  /** Path pattern using OpenAPI format with {param} syntax */
  path: string;
  /** Request validation schemas */
  request?: RequestTypes;
  /** Response schemas by status code */
  responses: Record<string | number, ResponseObject>;
  /** OpenAPI operation metadata */
  tags?: string[];
  summary?: string;
  description?: string;
  operationId?: string;
  /** Security requirements */
  security?: SecurityRequirement[];
}

Request Validation Types

Configuration for validating different parts of incoming requests.

/**
 * Request validation schema types
 */
interface RequestTypes {
  /** Path parameter validation */
  params?: ZodType;
  /** Query parameter validation */
  query?: ZodType;
  /** Cookie validation */
  cookies?: ZodType;
  /** Header validation (keys must be lowercase) */
  headers?: ZodType | ZodType[];
  /** Request body validation */
  body?: ZodRequestBody;
}

/**
 * Request body configuration with content types
 */
interface ZodRequestBody {
  /** Whether request body is required */
  required?: boolean;
  /** Content type schemas */
  content: ZodContentObject;
}

interface ZodContentObject {
  [mediaType: string]: ZodMediaTypeObject;
}

interface ZodMediaTypeObject {
  /** Zod schema for this content type */
  schema: ZodType;
}

Usage Examples:

// Route with comprehensive request validation
const complexRoute = createRoute({
  method: 'put',
  path: '/users/{id}/profile',
  request: {
    // Path parameters
    params: z.object({
      id: z.string().uuid(),
    }),
    // Query parameters
    query: z.object({
      notify: z.enum(['true', 'false']).optional(),
      fields: z.string().optional(),
    }),
    // Headers (must be lowercase)
    headers: z.object({
      authorization: z.string(),
      'content-type': z.literal('application/json'),
    }),
    // Request body
    body: {
      content: {
        'application/json': {
          schema: z.object({
            name: z.string().min(1),
            bio: z.string().max(500).optional(),
            avatar: z.string().url().optional(),
          }),
        },
      },
      required: true,
    },
  },
  responses: {
    200: {
      content: {
        'application/json': {
          schema: z.object({
            id: z.string(),
            name: z.string(),
            bio: z.string().optional(),
            avatar: z.string().optional(),
          }),
        },
      },
      description: 'Profile updated successfully',
    },
  },
});

Route Middleware Configuration

Configure middleware at the route level for specific functionality.

/**
 * Route-specific middleware configuration
 */
interface RouteConfig {
  /** Single middleware or array of middleware handlers */
  middleware?: MiddlewareHandler | MiddlewareHandler[];
}

Usage Examples:

import { prettyJSON } from 'hono/pretty-json';
import { cache } from 'hono/cache';

// Single middleware
const routeWithAuth = createRoute({
  method: 'get',
  path: '/protected',
  middleware: authMiddleware,
  responses: {
    200: {
      content: { 'application/json': { schema: z.object({}) } },
      description: 'Success',
    },
  },
});

// Multiple middleware (use 'as const' for proper type inference)
const routeWithMultiple = createRoute({
  method: 'get',
  path: '/cached-pretty',
  middleware: [
    prettyJSON(),
    cache({ cacheName: 'my-cache' }),
  ] as const,
  responses: {
    200: {
      content: { 'application/json': { schema: z.object({}) } },
      description: 'Success',
    },
  },
});

// Alternative: Apply middleware after route creation
app.use(routeWithAuth.getRoutingPath(), authMiddleware);
app.openapi(routeWithAuth, handler);

Response Configuration

Define response schemas for different status codes and content types.

/**
 * Response configuration by status code
 */
interface ResponseObject {
  /** Response content by media type */
  content?: {
    [mediaType: string]: {
      schema: ZodType;
    };
  };
  /** Response description (required) */
  description: string;
  /** Response headers */
  headers?: Record<string, any>;
}

Usage Examples:

// Multiple response types
const routeWithMultipleResponses = createRoute({
  method: 'post',
  path: '/upload',
  request: {
    body: {
      content: {
        'multipart/form-data': {
          schema: z.object({
            file: z.any(), // Use z.any() for file uploads
            description: z.string().optional(),
          }),
        },
      },
    },
  },
  responses: {
    200: {
      content: {
        'application/json': {
          schema: z.object({
            url: z.string(),
            size: z.number(),
          }),
        },  
      },
      description: 'File uploaded successfully',
    },
    400: {
      content: {
        'application/json': {
          schema: z.object({
            error: z.string(),
            code: z.string(),
          }),
        },
      },
      description: 'Invalid file or request',
    },
    413: {
      description: 'File too large',
    },
  },
});

// Text response
const textRoute = createRoute({
  method: 'get',
  path: '/health',
  responses: {
    200: {
      content: {
        'text/plain': {
          schema: z.string(),
        },
      },
      description: 'Health check',
    },
  },
});

OpenAPI Metadata

Additional OpenAPI operation metadata for documentation.

interface RouteConfig {
  /** Operation tags for grouping */
  tags?: string[];
  /** Brief operation summary */
  summary?: string;
  /** Detailed operation description */
  description?: string;
  /** Unique operation identifier */
  operationId?: string;
  /** Security requirements */
  security?: SecurityRequirement[];
  /** Hide from documentation */
  hide?: boolean;
}

Usage Examples:

// Fully documented route
const documentedRoute = createRoute({
  method: 'get',
  path: '/users/{id}',
  tags: ['Users'],
  summary: 'Get user by ID',
  description: 'Retrieves a single user by their unique identifier',
  operationId: 'getUserById',
  security: [{ Bearer: [] }],
  request: {
    params: z.object({
      id: z.string().uuid().openapi({
        description: 'Unique user identifier',
        example: '123e4567-e89b-12d3-a456-426614174000',
      }),
    }),
  },
  responses: {
    200: {
      content: {
        'application/json': {
          schema: UserSchema,
        },
      },
      description: 'User found and returned',
    },
  },
});

// Hidden route (excluded from docs)
const internalRoute = createRoute({
  method: 'post',
  path: '/internal/reset',
  hide: true,
  responses: {
    200: {
      description: 'Reset completed',
    },
  },
});

Path Parameter Conversion

Routes use OpenAPI path syntax {param} but are converted to Hono syntax :param for routing.

/**
 * Converts OpenAPI path format to Hono routing format
 */
type ConvertPathType<T extends string> = T extends `${infer Start}/{${infer Param}}${infer Rest}`
  ? `${Start}/:${Param}${ConvertPathType<Rest>}`
  : T;

type RoutingPath<P extends string> = ConvertPathType<P>;

Usage Examples:

const route = createRoute({
  path: '/users/{id}/posts/{postId}', // OpenAPI format
  // ... other config
});

// Get Hono-compatible path
const honoPath = route.getRoutingPath(); // "/users/:id/posts/:postId"

// Use for middleware registration
app.use(route.getRoutingPath(), middleware);
app.openapi(route, handler);

docs

core-openapi.md

index.md

openapi-generation.md

route-creation.md

validation-error-handling.md

tile.json