Adapters: Integrating with Routers
Chanfana is designed to be router-agnostic, allowing you to integrate it with various JavaScript web routers. Adapters are the bridge that connects Chanfana's OpenAPI functionality to specific router implementations. Currently, Chanfana provides adapters for Hono and itty-router, two popular choices for modern JavaScript runtimes, especially Cloudflare Workers.
Introduction to Adapters
Adapters in Chanfana serve the following key purposes:
- Router Integration: They provide specific functions and classes to seamlessly integrate Chanfana's OpenAPI schema generation, validation, and documentation features into the routing mechanism of a particular router library.
- Request Handling Abstraction: Adapters abstract away the router-specific details of request and response handling, allowing Chanfana's core logic to remain router-independent.
- Middleware Compatibility: They ensure compatibility with the middleware ecosystem of the target router, allowing you to use existing middleware alongside Chanfana's features.
Chanfana provides two main adapters:
- Hono Adapter (
fromHono
): For integrating with Hono applications. - Itty Router Adapter (
fromIttyRouter
): For integrating with itty-router applications.
Hono Adapter (fromHono
)
The fromHono
adapter is used to extend your Hono applications with Chanfana's OpenAPI capabilities. It provides the fromHono
function and the HonoOpenAPIRouterType
type.
Setting up Chanfana with Hono
To integrate Chanfana into your Hono application, you use the fromHono
function.
Example: Basic Hono Integration
import { Hono, type Context } from 'hono';
import { fromHono, OpenAPIRoute } from 'chanfana';
import { z } from 'zod';
export type Env = {
// Example bindings
DB: D1Database
BUCKET: R2Bucket
}
export type AppContext = Context<{ Bindings: Env }>
class MyEndpoint extends OpenAPIRoute {
schema = {
responses: {
"200": { description: 'Success' },
},
};
async handle(c: AppContext) {
return { message: 'Hello from Hono!' };
}
}
const app = new Hono<{ Bindings: Env }>();
// Initialize Chanfana for Hono using fromHono
const openapi = fromHono(app);
// Register your OpenAPIRoute endpoints using the openapi instance
openapi.get('/hello', MyEndpoint);
export default app;
Explanation:
- Import
fromHono
: Import thefromHono
function fromchanfana/adapters/hono
. - Create a Hono App: Create a standard Hono application instance using
new Hono()
. - Initialize Chanfana with
fromHono
: CallfromHono(app, options)
to initialize Chanfana for your Hono app.- The first argument is your Hono application instance (
app
). - The second argument is an optional
RouterOptions
object to configure Chanfana (e.g.,openapi_url
,docs_url
).
- The first argument is your Hono application instance (
- Use
openapi
to Register Routes: Use theopenapi
instance (returned byfromHono
) to register yourOpenAPIRoute
classes for different HTTP methods (get
,post
,put
,delete
,patch
,all
,on
,route
). These methods work similarly to Hono's routing methods but are extended with Chanfana's OpenAPI features.
Extending Existing Hono Applications
fromHono
is designed to be non-intrusive and can be easily integrated into existing Hono applications without requiring major code changes. You can gradually add OpenAPI documentation and validation to your existing routes by converting your route handlers to OpenAPIRoute
classes and registering them using the openapi
instance.
Example: Extending an Existing Hono App
import { Hono, type Context } from 'hono';
import { fromHono, OpenAPIRoute } from 'chanfana';
export type Env = {
// Example bindings, use your own
DB: D1Database
BUCKET: R2Bucket
}
export type AppContext = Context<{ Bindings: Env }>
const app = new Hono<{ Bindings: Env }>();
// Existing Hono route (without OpenAPI)
app.get('/legacy-route', (c) => c.text('This is a legacy route'));
// Initialize Chanfana
const openapi = fromHono(app);
// New OpenAPI-documented route
class NewEndpoint extends OpenAPIRoute {
schema = {
responses: {
"200": { description: 'Success' },
},
};
async handle(c: AppContext) {
return { message: 'This is a new OpenAPI route!' };
}
}
openapi.get('/new-route', NewEndpoint);
export default app;
In this example, we have an existing Hono route /legacy-route
that is not managed by Chanfana. We then initialize Chanfana using fromHono
and register a new route /new-route
using OpenAPIRoute
and openapi.get()
. Both routes will coexist in the same Hono application. Only the /new-route
will have OpenAPI documentation and validation.
HonoOpenAPIRouterType
The fromHono
function returns an object of type HonoOpenAPIRouterType
. This type is an intersection of Hono
and OpenAPIRouterType
, extending the standard Hono application instance with Chanfana's OpenAPI routing methods and properties.
Key extensions provided by HonoOpenAPIRouterType
:
- OpenAPI Routing Methods:
get()
,post()
,put()
,delete()
,patch()
,all()
,on()
,route()
methods are extended to handleOpenAPIRoute
classes and automatically register them for OpenAPI documentation and validation. original
Property: Provides access to the original Hono application instance.options
Property: Provides access to theRouterOptions
passed tofromHono
.registry
Property: Provides access to the OpenAPI registry used by Chanfana to collect schema definitions.schema()
Method: Returns the generated OpenAPI schema as a JavaScript object.
Example with Hono
Refer to the Quick Start with Hono section for a complete example of setting up Chanfana with Hono and creating a basic endpoint.
Itty Router Adapter (fromIttyRouter
)
The fromIttyRouter
adapter is used to integrate Chanfana with itty-router applications. It provides the fromIttyRouter
function and the IttyRouterOpenAPIRouterType
type.
Setting up Chanfana with Itty Router
To integrate Chanfana into your itty-router application, you use the fromIttyRouter
function.
Example: Basic Itty Router Integration
import { Router } from 'itty-router';
import { fromIttyRouter, OpenAPIRoute } from 'chanfana';
import { z } from 'zod';
class MyEndpoint extends OpenAPIRoute {
schema = {
responses: {
"200": { description: 'Success' },
},
};
async handle(request: Request, env, ctx) {
return { message: 'Hello from itty-router!' };
}
}
const router = Router();
// Initialize Chanfana for itty-router using fromIttyRouter
const openapi = fromIttyRouter(router);
// Register your OpenAPIRoute endpoints using the openapi instance
openapi.get('/hello', MyEndpoint);
// Add a default handler for itty-router (required)
router.all('*', () => new Response("Not Found.", { status: 404 }));
export const fetch = router.handle; // Export the fetch handler
Explanation:
- Import
fromIttyRouter
: Import thefromIttyRouter
function fromchanfana/adapters/ittyRouter
. - Create an Itty Router Instance: Create an itty-router instance using
Router()
. - Initialize Chanfana with
fromIttyRouter
: CallfromIttyRouter(router, options)
to initialize Chanfana for your itty-router instance.- The first argument is your itty-router instance (
router
). - The second argument is the optional
RouterOptions
object.
- The first argument is your itty-router instance (
- Use
openapi
to Register Routes: Use theopenapi
instance to register yourOpenAPIRoute
classes for different HTTP methods (get
,post
,put
,delete
,patch
,all
). These methods extend itty-router's routing methods with Chanfana's OpenAPI features. - Add Default Handler: Itty-router requires a default handler to be registered using
router.all('*', ...)
. This is necessary for itty-router to function correctly. - Export
fetch
Handler: Export therouter.handle
function asfetch
. This is the standard way to export an itty-router application for Cloudflare Workers or other Fetch API environments.
Extending Existing Itty Router Applications
Similar to Hono, fromIttyRouter
can be integrated into existing itty-router applications without major refactoring. You can gradually add OpenAPI documentation and validation to your routes.
IttyRouterOpenAPIRouterType
The fromIttyRouter
function returns an object of type IttyRouterOpenAPIRouterType
. This type extends the original itty-router instance with Chanfana's OpenAPI routing methods and properties, similar to HonoOpenAPIRouterType
.
Example with Itty Router
Refer to the Quick Start with Itty Router section for a complete example of setting up Chanfana with itty-router and creating a basic endpoint.
Choosing the Right Adapter
Choose the adapter that corresponds to the web router you are using in your project:
- Use
fromHono
for Hono applications. - Use
fromIttyRouter
for itty-router applications.
If you are using a different router, you might need to create a custom adapter. Chanfana's architecture is designed to be extensible, and creating a new adapter is possible, although it might require a deeper understanding of Chanfana's internals and the target router's API.