@node-openapi/fastify v0.1.1
@node-openapi/fastify
Fastify adapter for
@node-openapi/coreā define Zod-validated routes, generate OpenAPI 3.1 docs, and send type-safe responses in Fastify.
Read more in the core library docs.
Table of Contents
Installation
Install the adapter along with its peer dependencies:
# npm
npm install fastify @node-openapi/fastify
# yarn
yarn add fastify @node-openapi/fastify
# pnpm
pnpm add fastify @node-openapi/fastifyEnsure you have a compatible version of Fastify (v4+) and Zod (v3+).
Quick Start
Create a minimal Fastify server with a GET /ping route and serve the OpenAPI JSON at /docs.
import Fastify from 'fastify';
import { OpenAPIRouter, createRoute, z } from '@node-openapi/fastify';
const app = Fastify();
// 1. Initialize the router
const router = new OpenAPIRouter();
// 2. Define a simple ping route
const pingRoute = createRoute({
method: 'get',
path: '/ping', // OpenAPI path
getRoutingPath: () => '/ping', // Fastify path
request: {},
responses: {
200: {
content: {
'application/json': { schema: z.object({ message: z.string() }) },
},
},
},
});
router.route(pingRoute, async ({ h }) => {
h.json({ message: 'pong' });
});
// 3. Serve OpenAPI docs
router.doc('/docs', {
openapi: '3.1.0',
info: { title: 'API', version: '1.0.0' },
});
// 4. Register the router with the Fastify app
router.registerApp(app);
// 5. Start server
app.listen({ port: 3000 }, () => {
console.log('š Server running at http://localhost:3000');
console.log('š API docs available at http://localhost:3000/docs');
});API Reference
new OpenAPIRouter(options?)
options.validateResponse?: booleanā (defaulttrue) Enable or disable runtime response validation against your OpenAPI schemas in thehhelper.
.middleware(handler)
Register global middleware for all routes defined on this router instance and its children.
The handler function receives request, reply, and an object containing context.
The context object is shared across middlewares and the final route handler for a given request.
const router = new OpenAPIRouter<{ user?: { id: string } }>();
router.middleware(async (request, reply, { context }) => {
const userId = request.headers['x-user-id'];
if (typeof userId === 'string') {
context.user = { id: userId };
}
});.route(routeConfig, handler)
Define a handler for a route. The handler will run after all middlewares and request validation. The handler will receive an object with the following properties:
request: the native Fastify requestreply: the native Fastify replyinput: validated request data (param, query, header, cookie, form, json)context: any values attached by your middlewareh: a typed helper for sendingjsonortextresponses. The typing is based on the response schema in the route config. The helper will also validate the response data if thevalidateResponseoption is enabled.
router.route(myRouteConfig, async ({ input, context, h }) => {
// ... your logic ...
// The data type is inferred by the status, and the default status is 200.
h.json({ data: result }); // Responds with status 200 by default
// h.json({ error: 'Not found' }, 404);
});.use(path, subRouter)
Mount a child OpenAPIRouter under a base path and merge its OpenAPI definitions. Middlewares from the parent router will be applied to the sub-router's routes.
const adminRouter = new OpenAPIRouter();
// Define routes on adminRouter...
router.use('/admin', adminRouter);.doc(path, openapiConfig)
Serve the merged OpenAPI document as JSON at path.
router.doc('/openapi.json', {
openapi: '3.1.0',
info: { title: 'My Service', version: '1.2.3' },
});.registerApp(app)
Registers all defined routes and middlewares with the provided Fastify application instance. This method should be called after all routes, middlewares, and sub-routers have been defined.
const app = Fastify();
const router = new OpenAPIRouter();
// ... define routes, middlewares, use sub-routers ...
router.registerApp(app);createRoute
Re-exported helper from @node-openapi/core to define RouteConfig objects.
It requires a getRoutingPath() method that returns the Fastify-specific path string (e.g., using :param for route parameters).
const articleRoute = createRoute({
method: 'get',
path: '/articles/{slug}', // OpenAPI path
getRoutingPath: () => '/articles/:slug', // Fastify path
request: {
params: z.object({ slug: z.string() }),
},
// ...responses
});z
Re-exported Zod instance from @node-openapi/core for defining schemas. It has additional types for OpenAPI documentation under .openapi(). You can read more about the options from @asteasolutions/zod-to-openapi.
const userSchema = z
.object({
id: z.string(),
name: z.string(),
})
.openapi('User');Configuration
- Response validation: disable by
new OpenAPIRouter({ validateResponse: false }). - Path parameters: Remember that
createRoute'spathis for OpenAPI (e.g.,/users/{id}), whilegetRoutingPath()is for Fastify (e.g.,/users/:id).
Examples
See a complete example with authentication and CRUD routes in the examples/fastify folder:
examples/fastify/
āā package.json
āā tsconfig.json
āā src/
āā factories.ts # auth middleware factories
āā controller/
ā āā articles.controller.ts
ā āā user.controller.ts
ā āā ... (other controllers)
āā routes/
ā āā articles.routes.ts
āā index.ts # main Fastify server setupAdvanced Usage
- Context Extension: Use
.extend()on a router to create derived router instances with extendedTContexttypes. This is useful for gradually adding typed properties to the context through middlewares. - Error handling: Zod validation errors or errors thrown in handlers are caught by Fastify's
setErrorHandler. You can customize this to format error responses. See the exampleindex.ts. - Middleware Ordering: Middlewares registered with
.middleware()are applied in the order they are defined. They run before the route's input validation and the main handler.
License
This project is licensed under the MIT License. See the LICENSE file for details.