0.1.0 • Published 5 months ago

@node-openapi/hono v0.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

@node-openapi/hono

Hono adapter for @node-openapi/core — define Zod-validated routes, generate OpenAPI 3.1 docs, and send type-safe responses in Hono.

Read more in the core library docs.


Table of Contents


Installation

Install the adapter along with its peer dependencies:

# npm
npm install hono @node-openapi/hono

# yarn
yarn add hono @node-openapi/hono

# pnpm
pnpm add hono @node-openapi/hono

Ensure you have a compatible version of Hono (v3+) and Zod (v3+).


Quick Start

Create a minimal Hono server with a GET /ping route and serve the OpenAPI JSON at /openapi.json.

import { Hono } from 'hono';
import { OpenAPIRouter, createRoute, z } from '@node-openapi/hono';

const app = new Hono();

// 1. Initialize the router. Optionally pass the main Hono app.
const router = new OpenAPIRouter({ app }); // Or new OpenAPIRouter(); then app.route('/', router.app);

// 2. Define a simple ping route
const pingRoute = createRoute({
  method: 'get',
  path: '/ping', // OpenAPI path
  getRoutingPath: () => '/ping', // Hono path (can use :param for params)
  request: {},
  responses: {
    200: {
      content: {
        'application/json': { schema: z.object({ message: z.string() }) },
      },
    },
  },
});

router.route(pingRoute, (c) => {
  return c.typedJson({ message: 'pong' }, 200);
});

// 3. Serve OpenAPI docs
router.doc('/openapi.json', {
  openapi: '3.1.0',
  info: { title: 'My Hono API', version: '1.0.0' },
});

// If router was initialized without `app`:
// app.route('/', router.app);

// 4. Export or serve the app (e.g., for Cloudflare Workers, Deno, Node.js with @hono/node-server)
export default app;

// Example for Node.js server:
// import { serve } from '@hono/node-server';
// serve({ fetch: app.fetch, port: 3000 }, () => {
//   console.log('šŸš€ Server running at http://localhost:3000');
//   console.log('šŸ“– API docs available at http://localhost:3000/openapi.json');
// });

API Reference

new OpenAPIRouter(options?)

  • options.app?: Hono<E> — Provide an existing Hono app instance. If not provided, a new Hono<E>() is created and can be accessed via router.app.
  • options.validateResponse?: boolean — (default true) Enable or disable runtime response validation for c.typedJson() and c.typedText() against your OpenAPI schemas.

.middleware(handler)

Register a Hono MiddlewareHandler for all routes defined on this router instance after this call.

type MyEnv = { Variables: { user?: { id: string } } };
const router = new OpenAPIRouter<MyEnv>();

router.middleware(async (c, next) => {
  // c.set('user', await authenticateUser(c.req.header('Authorization')));
  await next();
});

.route(routeConfig, ...handlers)

Define one or more Hono handlers for a route. Middlewares registered on the router are applied first, then input validation, then your handlers. The Hono context c is augmented with c.typedJson() and c.typedText() for type-safe, schema-validated responses. Validated input is available via c.req.valid('param' | 'query' | 'json' | ...).

router.route(myRouteConfig, (c) => {
  const params = c.req.valid('param');
  // const user = c.var.user; // From middleware
  // ... your logic ...
  return c.typedJson({ data: result }, 200);
});

.use(path, subRouter)

Mount another OpenAPIRouter's Hono app under a base path and merge its OpenAPI definitions.

const adminApiRouter = new OpenAPIRouter();
// define routes on adminApiRouter.app ...
mainRouter.use('/admin', adminApiRouter);

.doc(path, openapiConfig, additionalDefinitions?)

Serve the merged OpenAPI document as JSON at path.

  • additionalDefinitions?: OpenAPIDefinitions[] - Optional array of Zod schemas to be included as reusable components in the OpenAPI document.
router.doc('/docs/openapi.json', {
  openapi: '3.1.0',
  info: { title: 'My Service', version: '1.2.3' },
});

app (property)

The Hono application instance (Hono<E>) associated with this router. You can use this to register non-OpenAPI routes, or mount this router's app into another Hono app using parentApp.route('/prefix', router.app).

createRoute

Re-exported helper from @node-openapi/core to define RouteConfig objects. It requires a getRoutingPath() method that returns the Hono-specific path string (e.g., using :param for route parameters).

const articleRoute = createRoute({
  method: 'get',
  path: '/articles/{slug}', // OpenAPI path
  getRoutingPath: () => '/articles/:slug', // Hono path
  request: {
    params: z.object({ slug: z.string() }),
  },
  // ...responses
});

z

Re-exported Zod instance from @node-openapi/core. Use z.openapi() for schema-level OpenAPI extensions. See @asteasolutions/zod-to-openapi.

const userSchema = z
  .object({
    id: z.string(),
    name: z.string(),
  })
  .openapi('User'); // Makes 'User' available as a reusable schema component

Configuration

  • Response validation: Disable by new OpenAPIRouter({ validateResponse: false }).
  • Path parameters: createRoute's path is for OpenAPI (e.g., /users/{id}), while getRoutingPath() is for Hono (e.g., /users/:id).

Examples

See a complete example with authentication and CRUD routes in the examples/hono folder:

examples/hono/
ā”œā”€ package.json
ā”œā”€ tsconfig.json
└─ src/
   ā”œā”€ factories.ts        # auth middleware factories
   ā”œā”€ controller/
   │  ā”œā”€ articles.controller.ts
   │  ā”œā”€ user.controller.ts
   │  └─ ... (other controllers)
   ā”œā”€ routes/
   │  ā”œā”€ articles.routes.ts
   │  └─ security.ts       # Bearer security definition
   └─ index.ts            # main Hono server setup

Advanced Usage

  • Context Extension (c.var): Use .extend<NewEnv>() to create routers with more specific Hono Environment types. Middlewares can then use c.set('key', value) to populate c.var.key in a type-safe manner for subsequent handlers.
  • Error handling: Zod validation errors are automatically caught by an internal middleware and result in a 400 JSON response. Other errors thrown in handlers can be managed using Hono's standard app.onError((err, c) => ...) mechanism. See the example index.ts.
  • Middleware Ordering: .middleware() calls apply to routes defined after the middleware call on that specific router instance.

License

This project is licensed under the MIT License. See the LICENSE file for details.