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

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