Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/turkerdev/fastify-type-provider-zod
https://github.com/turkerdev/fastify-type-provider-zod
Last synced: 2 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/turkerdev/fastify-type-provider-zod
- Owner: turkerdev
- License: mit
- Created: 2022-03-23T16:53:49.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-11-14T22:31:22.000Z (about 2 months ago)
- Last Synced: 2025-01-04T01:12:45.562Z (8 days ago)
- Language: TypeScript
- Size: 146 KB
- Stars: 424
- Watchers: 6
- Forks: 25
- Open Issues: 43
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
- awesome-zod - `fastify-type-provider-zod` - Create Fastify type providers from Zod schemas. (APIs and Servers)
README
# Fastify Type Provider Zod
[![NPM Version](https://img.shields.io/npm/v/fastify-type-provider-zod.svg)](https://npmjs.org/package/fastify-type-provider-zod)
[![NPM Downloads](https://img.shields.io/npm/dm/fastify-type-provider-zod.svg)](https://npmjs.org/package/fastify-type-provider-zod)
[![Build Status](https://github.com//turkerdev/fastify-type-provider-zod/workflows/CI/badge.svg)](https://github.com//turkerdev/fastify-type-provider-zod/actions)## How to use?
```js
import Fastify from "fastify";
import { serializerCompiler, validatorCompiler, ZodTypeProvider } from "fastify-type-provider-zod";
import z from "zod";const app = Fastify()
// Add schema validator and serializer
app.setValidatorCompiler(validatorCompiler);
app.setSerializerCompiler(serializerCompiler);app.withTypeProvider().route({
method: "GET",
url: "/",
// Define your schema
schema: {
querystring: z.object({
name: z.string().min(4),
}),
response: {
200: z.string(),
},
},
handler: (req, res) => {
res.send(req.query.name);
},
});app.listen({ port: 4949 });
```You can also pass options to the `serializerCompiler` function:
```ts
type ZodSerializerCompilerOptions = {
replacer?: ReplacerFunction;
};
``````js
import Fastify from 'fastify';
import { createSerializerCompiler, validatorCompiler } from 'fastify-type-provider-zod';
import z from 'zod';const app = Fastify();
const replacer = function (key, value) {
if (this[key] instanceof Date) {
return { _date: value.toISOString() };
}
return value;
};// Create a custom serializer compiler
const customSerializerCompiler = createSerializerCompiler({ replacer });// Add schema validator and serializer
app.setValidatorCompiler(validatorCompiler);
app.setSerializerCompiler(customSerializerCompiler);// ...
app.listen({ port: 4949 });
```## How to use together with @fastify/swagger
```ts
import fastify from 'fastify';
import fastifySwagger from '@fastify/swagger';
import fastifySwaggerUI from '@fastify/swagger-ui';
import { z } from 'zod';import {
jsonSchemaTransform,
createJsonSchemaTransform,
serializerCompiler,
validatorCompiler,
ZodTypeProvider,
} from 'fastify-type-provider-zod';const app = fastify();
app.setValidatorCompiler(validatorCompiler);
app.setSerializerCompiler(serializerCompiler);app.register(fastifySwagger, {
openapi: {
info: {
title: 'SampleApi',
description: 'Sample backend service',
version: '1.0.0',
},
servers: [],
},
transform: jsonSchemaTransform,// You can also create transform with custom skiplist of endpoints that should not be included in the specification:
//
// transform: createJsonSchemaTransform({
// skipList: [ '/documentation/static/*' ]
// })
});app.register(fastifySwaggerUI, {
routePrefix: '/documentation',
});const LOGIN_SCHEMA = z.object({
username: z.string().max(32).describe('Some description for username'),
password: z.string().max(32),
});app.after(() => {
app.withTypeProvider().route({
method: 'POST',
url: '/login',
schema: { body: LOGIN_SCHEMA },
handler: (req, res) => {
res.send('ok');
},
});
});async function run() {
await app.ready();await app.listen({
port: 4949,
});console.log(`Documentation running at http://localhost:4949/documentation`);
}run();
```## Customizing error responses
You can add custom handling of request and response validation errors to your fastify error handler like this:
```ts
import { hasZodFastifySchemaValidationErrors } from 'fastify-type-provider-zod'fastifyApp.setErrorHandler((err, req, reply) => {
if (hasZodFastifySchemaValidationErrors(err)) {
return reply.code(400).send({
error: 'Response Validation Error',
message: "Request doesn't match the schema",
statusCode: 400,
details: {
issues: err.validation,
method: req.method,
url: req.url,
},
})
}if (isResponseSerializationError(err)) {
return reply.code(500).send({
error: 'Internal Server Error',
message: "Response doesn't match the schema",
statusCode: 500,
details: {
issues: err.cause.issues,
method: err.method,
url: err.url,
},
})
}
// the rest of the error handler
})
```## How to create refs to the schemas?
It is possible to create refs to the schemas by using the `createJsonSchemaTransformObject` function. You provide the schemas as an object and fastifySwagger will create a OpenAPI document in which the schemas are referenced. The following example creates a ref to the `User` schema and will include the `User` schema in the OpenAPI document.
```ts
import fastifySwagger from '@fastify/swagger';
import fastifySwaggerUI from '@fastify/swagger-ui';
import fastify from 'fastify';
import { z } from 'zod';
import type { ZodTypeProvider } from 'fastify-type-provider-zod';
import {
createJsonSchemaTransformObject,
jsonSchemaTransform,
serializerCompiler,
validatorCompiler,
} from 'fastify-type-provider-zod';const USER_SCHEMA = z.object({
id: z.number().int().positive(),
name: z.string().describe('The name of the user'),
});const app = fastify();
app.setValidatorCompiler(validatorCompiler);
app.setSerializerCompiler(serializerCompiler);app.register(fastifySwagger, {
openapi: {
info: {
title: 'SampleApi',
description: 'Sample backend service',
version: '1.0.0',
},
servers: [],
},
transform: jsonSchemaTransform,
transformObject: createJsonSchemaTransformObject({
schemas: {
User: USER_SCHEMA,
},
}),
});app.register(fastifySwaggerUI, {
routePrefix: '/documentation',
});app.after(() => {
app.withTypeProvider().route({
method: 'GET',
url: '/users',
schema: {
response: {
200: USER_SCHEMA.array(),
},
},
handler: (req, res) => {
res.send([]);
},
});
});async function run() {
await app.ready();await app.listen({
port: 4949,
});console.log(`Documentation running at http://localhost:4949/documentation`);
}run();
```## How to create a plugin?
```ts
import { z } from 'zod';
import { FastifyPluginAsyncZod } from 'fastify-type-provider-zod';const plugin: FastifyPluginAsyncZod = async function (fastify, _opts) {
fastify.route({
method: 'GET',
url: '/',
// Define your schema
schema: {
querystring: z.object({
name: z.string().min(4),
}),
response: {
200: z.string(),
},
},
handler: (req, res) => {
res.send(req.query.name);
},
});
};
```