Skip to content

Commit 0350105

Browse files
authored
Update serialization logic (#226)
1 parent df8ae4f commit 0350105

File tree

5 files changed

+100
-1
lines changed

5 files changed

+100
-1
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,16 @@ const customSerializerCompiler = createSerializerCompiler({
223223
});
224224
```
225225

226+
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.
227+
228+
If you have other routes with response schemas which are not Zod Schemas, you can supply a `fallbackSerializer` to `createSerializerCompiler`.
229+
230+
```ts
231+
const customSerializerCompiler = createSerializerCompiler({
232+
fallbackSerializer: ({ schema, url, method }) => customSerializer(schema),
233+
});
234+
```
235+
226236
Please note: the `responses`, `parameters` components do not appear to be supported by the `@fastify/swagger` library.
227237

228238
### Create Document Options

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"@crackle/cli": "0.15.5",
6262
"@fastify/swagger": "9.4.2",
6363
"@fastify/swagger-ui": "5.2.1",
64+
"@fastify/under-pressure": "9.0.3",
6465
"@types/node": "22.10.7",
6566
"eslint-plugin-zod-openapi": "1.0.0",
6667
"fastify": "5.2.1",

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/serializerCompiler.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import 'zod-openapi/extend';
2+
3+
import UnderPressure from '@fastify/under-pressure';
24
import fastify from 'fastify';
35
import { z } from 'zod';
46
import type { ZodOpenApiResponsesObject } from 'zod-openapi';
@@ -74,6 +76,72 @@ describe('serializerCompiler', () => {
7476
expect(result.json()).toEqual({ jobId: '60002023' });
7577
});
7678

79+
it('should handle a route with a JSON schema', async () => {
80+
const app = fastify();
81+
82+
app.setSerializerCompiler(serializerCompiler);
83+
app.post(
84+
'/',
85+
{
86+
schema: {
87+
response: {
88+
200: {
89+
type: 'object',
90+
properties: {
91+
jobId: { type: 'string' },
92+
},
93+
},
94+
},
95+
},
96+
},
97+
async (_req, res) =>
98+
res.send({
99+
jobId: '60002023',
100+
}),
101+
);
102+
103+
await app.ready();
104+
105+
const result = await app.inject().post('/');
106+
107+
expect(result.json()).toEqual({ jobId: '60002023' });
108+
});
109+
110+
it('should work with under pressure', async () => {
111+
const app = fastify();
112+
113+
app.register(UnderPressure, {
114+
exposeStatusRoute: '/status/health-check',
115+
healthCheck: () => Promise.resolve(true),
116+
});
117+
app.setSerializerCompiler(serializerCompiler);
118+
app.post(
119+
'/',
120+
{
121+
schema: {
122+
response: {
123+
200: {
124+
type: 'object',
125+
properties: {
126+
jobId: { type: 'string' },
127+
},
128+
},
129+
},
130+
},
131+
},
132+
async (_req, res) =>
133+
res.send({
134+
jobId: '60002023',
135+
}),
136+
);
137+
138+
await app.ready();
139+
140+
const result = await app.inject().get('/status/health-check');
141+
142+
expect(result.json()).toEqual({ status: 'ok' });
143+
});
144+
77145
it('should fail an invalid response', async () => {
78146
const app = fastify();
79147

src/serializerCompiler.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,25 @@ import type { FastifySerializerCompiler } from 'fastify/types/schema';
66
import type { ZodType, ZodTypeAny } from 'zod';
77
import { createSchema } from 'zod-openapi';
88

9+
import { isZodType } from './transformer';
910
import { ResponseSerializationError } from './validationError';
1011

1112
export interface SerializerOptions {
1213
components?: Record<string, ZodTypeAny>;
1314
stringify?: (value: unknown) => string;
15+
fallbackSerializer?: FastifySerializerCompiler<ZodType>;
1416
}
1517

1618
export const createSerializerCompiler =
1719
(opts?: SerializerOptions): FastifySerializerCompiler<ZodType> =>
18-
({ schema, method, url }) => {
20+
(routeSchema) => {
21+
const { schema, url, method } = routeSchema;
22+
if (!isZodType(schema)) {
23+
return opts?.fallbackSerializer
24+
? opts.fallbackSerializer(routeSchema)
25+
: fastJsonStringify(schema);
26+
}
27+
1928
let stringify = opts?.stringify;
2029
if (!stringify) {
2130
const { schema: jsonSchema, components } = createSchema(schema, {

0 commit comments

Comments
 (0)