Gathering detailed insights and metrics for fastify-zod-openapi
Gathering detailed insights and metrics for fastify-zod-openapi
Gathering detailed insights and metrics for fastify-zod-openapi
Gathering detailed insights and metrics for fastify-zod-openapi
npm install fastify-zod-openapi
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (99.28%)
JavaScript (0.72%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
98 Stars
225 Commits
12 Forks
2 Watchers
5 Branches
7 Contributors
Updated on Jul 12, 2025
Latest Version
5.1.0
Package Id
fastify-zod-openapi@5.1.0
Unpacked Size
99.58 kB
Size
13.19 kB
File Count
7
NPM Version
10.8.2
Node Version
20.19.3
Published on
Jul 10, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
Fastify type provider, validation, serialization and @fastify/swagger support for zod-openapi.
Install via npm
, pnpm
or pnpm
:
1npm install zod fastify-zod-openapi 2## or 3yarn add zod fastify-zod-openapi 4## or 5pnpm install zod fastify-zod-openapi
1import fastify from 'fastify'; 2import { 3 type FastifyZodOpenApiSchema, 4 type FastifyZodOpenApiTypeProvider, 5 serializerCompiler, 6 validatorCompiler, 7} from 'fastify-zod-openapi'; 8import * as z from 'zod/v4'; 9 10const app = fastify(); 11 12app.setValidatorCompiler(validatorCompiler); 13app.setSerializerCompiler(serializerCompiler); 14 15app.withTypeProvider<FastifyZodOpenApiTypeProvider>().route({ 16 method: 'POST', 17 url: '/:jobId', 18 schema: { 19 body: z.object({ 20 jobId: z.string().meta({ 21 description: 'Job ID', 22 example: '60002023', 23 }), 24 }), 25 response: { 26 201: z.object({ 27 jobId: z.string().meta({ 28 description: 'Job ID', 29 example: '60002023', 30 }), 31 }), 32 }, 33 } satisfies FastifyZodOpenApiSchema, 34 handler: async (req, res) => { 35 await res.send({ jobId: req.body.jobId }); 36 }, 37}); 38 39await app.ready(); 40await app.listen({ port: 5000 });
1import fastify from 'fastify'; 2import { 3 type FastifyPluginAsyncZodOpenApi, 4 type FastifyZodOpenApiSchema, 5 serializerCompiler, 6 validatorCompiler, 7} from 'fastify-zod-openapi'; 8import * as z from 'zod/v4'; 9 10const app = fastify(); 11 12app.setValidatorCompiler(validatorCompiler); 13app.setSerializerCompiler(serializerCompiler); 14 15const plugin: FastifyPluginAsyncZodOpenApi = async (fastify, _opts) => { 16 fastify.route({ 17 method: 'POST', 18 url: '/', 19 // Define your schema 20 schema: { 21 body: z.object({ 22 jobId: z.string().meta({ 23 description: 'Job ID', 24 example: '60002023', 25 }), 26 }), 27 response: { 28 201: z.object({ 29 jobId: z.string().meta({ 30 description: 'Job ID', 31 example: '60002023', 32 }), 33 }), 34 }, 35 } satisfies FastifyZodOpenApiSchema, 36 handler: async (req, res) => { 37 await res.send({ jobId: req.body.jobId }); 38 }, 39 }); 40}; 41 42app.register(plugin);
1import fastifySwagger from '@fastify/swagger'; 2import fastifySwaggerUI from '@fastify/swagger-ui'; 3import fastify from 'fastify'; 4import { 5 type FastifyZodOpenApiSchema, 6 type FastifyZodOpenApiTypeProvider, 7 fastifyZodOpenApiPlugin, 8 fastifyZodOpenApiTransform, 9 fastifyZodOpenApiTransformObject, 10 serializerCompiler, 11 validatorCompiler, 12} from 'fastify-zod-openapi'; 13import * as z from 'zod/v4'; 14 15const app = fastify(); 16 17app.setValidatorCompiler(validatorCompiler); 18app.setSerializerCompiler(serializerCompiler); 19 20await app.register(fastifyZodOpenApiPlugin); 21await app.register(fastifySwagger, { 22 openapi: { 23 info: { 24 title: 'hello world', 25 version: '1.0.0', 26 }, 27 openapi: '3.1.0', 28 }, 29 transform: fastifyZodOpenApiTransform, 30 transformObject: fastifyZodOpenApiTransformObject, 31}); 32await app.register(fastifySwaggerUI, { 33 routePrefix: '/documentation', 34}); 35 36app.withTypeProvider<FastifyZodOpenApiTypeProvider>().route({ 37 method: 'POST', 38 url: '/', 39 schema: { 40 body: z.object({ 41 jobId: z.string().meta({ 42 description: 'Job ID', 43 example: '60002023', 44 }), 45 }), 46 response: { 47 201: { 48 content: { 49 'application/json': { 50 schema: z.object({ 51 jobId: z.string().meta({ 52 description: 'Job ID', 53 example: '60002023', 54 }), 55 }), 56 }, 57 }, 58 }, 59 }, 60 } satisfies FastifyZodOpenApiSchema, 61 handler: async (_req, res) => 62 res.send({ 63 jobId: '60002023', 64 }), 65}); 66await app.ready(); 67await app.listen({ port: 5000 });
This library allows you to easily declare components. As an example:
1const title = z.string().meta({ 2 description: 'Job title', 3 example: 'My job', 4 ref: 'jobTitle', // <- new field 5});
Wherever title
is used in your request/response schemas across your application, it will instead be created as a reference.
1{ "$ref": "#/components/schemas/jobTitle" }
For a further dive please follow the documentation here.
If you wish to declare the components manually you will need to do so via the plugin's options. You will also need to create a custom SerializerCompiler to make use of fast-json-stringify.
1const components: ZodOpenApiComponentsObject = { schemas: { mySchema } }; 2await app.register(fastifyZodOpenApiPlugin, { 3 components, 4}); 5 6const customSerializerCompiler = createSerializerCompiler({ 7 components, 8});
Alternatively, you can use JSON.stringify
instead.
1const customSerializerCompiler = createSerializerCompiler({ 2 stringify: JSON.stringify, 3});
By default, this library assumes that if a response schema provided is not a Zod Schema, it is a JSON Schema and will naively pass it straight into fast-json-stringify
. This will not work in conjunction with Fastify's schema registration.
If you have other routes with response schemas which are not Zod Schemas, you can supply a fallbackSerializer
to createSerializerCompiler
.
1const customSerializerCompiler = createSerializerCompiler({
2 fallbackSerializer: ({ schema, url, method }) => customSerializer(schema),
3});
Please note: the responses
, parameters
components do not appear to be supported by the @fastify/swagger
library.
If you wish to use CreateDocumentOptions, pass it in via the plugin options:
1await app.register(fastifyZodOpenApiPlugin, { 2 documentOpts: { 3 unionOneOf: true, 4 }, 5});
The default response serializer serializerCompiler
uses fast-json-stringify. Under the hood, the schema passed to the response is transformed using OpenAPI 3.1.0 and passed to fast-json-stringify
as a JSON Schema.
If are running into any compatibility issues or wish to restore the previous JSON.stringify
functionality, you can use the createSerializerCompiler
function.
1const customSerializerCompiler = createSerializerCompiler({ 2 stringify: JSON.stringify, 3});
By default, fastify-zod-openapi
emits request validation errors in a similar manner to fastify
when used in conjunction with it's native JSON Schema error handling.
As an example:
1{ 2 "code": "FST_ERR_VALIDATION", 3 "error": "Bad Request", 4 "message": "params/jobId Expected number, received string", 5 "statusCode": 400 6}
For responses, it will emit a 500 error along with a vague error which will protect your implementation details
1{ 2 "code": "FST_ERR_RESPONSE_SERIALIZATION", 3 "error": "Internal Server Error", 4 "message": "Response does not match the schema", 5 "statusCode": 500 6}
To customise this behaviour, you may follow the fastify error handling guidance.
This library throws a RequestValidationError
when a request fails to validate against your Zod Schemas
1fastify.setErrorHandler(function (error, request, reply) { 2 if (error.validation) { 3 const zodValidationErrors = error.validation.filter( 4 (err) => err instanceof RequestValidationError, 5 ); 6 const zodIssues = zodValidationErrors.map((err) => err.params.issue); 7 const originalError = zodValidationErrors?.[0]?.params.error; 8 return reply.status(422).send({ 9 zodIssues 10 originalError 11 }); 12 } 13});
1fastify.setSchemaErrorFormatter(function (errors, dataVar) { 2 let message = `${dataVar}:`; 3 for (const error of errors) { 4 if (error instanceof RequestValidationError) { 5 message += ` ${error.instancePath} ${error.keyword}`; 6 } 7 } 8 9 return new Error(message); 10}); 11 12// { 13// code: 'FST_ERR_VALIDATION', 14// error: 'Bad Request', 15// message: 'querystring: /jobId invalid_type', 16// statusCode: 400, 17// }
1app.withTypeProvider<FastifyZodOpenApiTypeProvider>().get( 2 '/', 3 { 4 schema: { 5 querystring: z.object({ 6 jobId: z.string().meta({ 7 description: 'Job ID', 8 example: '60002023', 9 }), 10 }), 11 }, 12 attachValidation: true, 13 }, 14 (req, res) => { 15 if (req.validationError?.validation) { 16 const zodValidationErrors = req.validationError.validation.filter( 17 (err) => err instanceof RequestValidationError, 18 ); 19 console.error(zodValidationErrors); 20 } 21 22 return res.send(req.query); 23 }, 24);
1app.setErrorHandler((error, _req, res) => { 2 if (error instanceof ResponseSerializationError) { 3 return res.status(500).send({ 4 error: 'Bad response', 5 }); 6 } 7}); 8 9// { 10// error: 'Bad response'; 11// }
fastify-type-provider-zod: Big kudos to this library for lighting the way with how to create type providers, validators and serializers. fastify-zod-openapi is just an extension to this library whilst adding support for the functionality of zod-openapi.
1pnpm install 2pnpm build
1pnpm test
1# Fix issues 2pnpm format 3 4# Check for issues 5pnpm lint
To release a new version
🏷️ Choose a tag
, enter a version number. eg. v1.2.0
and click + Create new tag: vX.X.X on publish
.Generate release notes
button and adjust the description.Set as the latest release
box and click Publish release
. This will trigger the Release
workflow.Pull Requests
tab for a PR labelled Release vX.X.X
.Merge Pull Request
on that Pull Request to update main with the new package version.To release a new beta version
🏷️ Choose a tag
, enter a version number with a -beta.X
suffix eg. v1.2.0-beta.1
and click + Create new tag: vX.X.X-beta.X on publish
.Generate release notes
button and adjust the description.Set as a pre-release
box and click Publish release
. This will trigger the Prerelease
workflow.No vulnerabilities found.
No security vulnerabilities found.