feat(fastify): add decorator for custom schema

Add an ability to attach json schema to request with a RequestSchema decorator
This commit is contained in:
Piotr Frankowski
2025-03-17 12:33:20 +01:00
parent 31ad231bfc
commit a5dab19b22
5 changed files with 45 additions and 2 deletions

View File

@@ -53,6 +53,7 @@ import { parse as querystringParse } from 'fast-querystring';
import { import {
FASTIFY_ROUTE_CONFIG_METADATA, FASTIFY_ROUTE_CONFIG_METADATA,
FASTIFY_ROUTE_CONSTRAINTS_METADATA, FASTIFY_ROUTE_CONSTRAINTS_METADATA,
FASTIFY_ROUTE_SCHEMA_METADATA,
} from '../constants'; } from '../constants';
import { NestFastifyBodyParserOptions } from '../interfaces'; import { NestFastifyBodyParserOptions } from '../interfaces';
import { import {
@@ -752,9 +753,14 @@ export class FastifyAdapter<
handlerRef, handlerRef,
); );
const routeSchema = Reflect.getMetadata(
FASTIFY_ROUTE_SCHEMA_METADATA,
handlerRef,
);
const hasConfig = !isUndefined(routeConfig); const hasConfig = !isUndefined(routeConfig);
const hasConstraints = !isUndefined(routeConstraints); const hasConstraints = !isUndefined(routeConstraints);
const hasSchema = !isUndefined(routeSchema);
const routeToInject: RouteOptions<TServer, TRawRequest, TRawResponse> & const routeToInject: RouteOptions<TServer, TRawRequest, TRawResponse> &
RouteShorthandOptions = { RouteShorthandOptions = {
method: routerMethodKey, method: routerMethodKey,
@@ -766,7 +772,7 @@ export class FastifyAdapter<
this.instance.addHttpMethod(routerMethodKey, { hasBody: true }); this.instance.addHttpMethod(routerMethodKey, { hasBody: true });
} }
if (isVersioned || hasConstraints || hasConfig) { if (isVersioned || hasConstraints || hasConfig || hasSchema) {
const isPathAndRouteTuple = args.length === 2; const isPathAndRouteTuple = args.length === 2;
if (isPathAndRouteTuple) { if (isPathAndRouteTuple) {
const constraints = { const constraints = {
@@ -783,6 +789,9 @@ export class FastifyAdapter<
...routeConfig, ...routeConfig,
}, },
}), }),
...(hasSchema && {
schema: routeSchema,
}),
}; };
const routeToInjectWithOptions = { ...routeToInject, ...options }; const routeToInjectWithOptions = { ...routeToInject, ...options };

View File

@@ -1,3 +1,4 @@
export const FASTIFY_ROUTE_CONFIG_METADATA = '__fastify_route_config__'; export const FASTIFY_ROUTE_CONFIG_METADATA = '__fastify_route_config__';
export const FASTIFY_ROUTE_CONSTRAINTS_METADATA = export const FASTIFY_ROUTE_CONSTRAINTS_METADATA =
'__fastify_route_constraints__'; '__fastify_route_constraints__';
export const FASTIFY_ROUTE_SCHEMA_METADATA = '__fastify_route_schema__';

View File

@@ -1,2 +1,3 @@
export * from './route-config.decorator'; export * from './route-config.decorator';
export * from './route-constraints.decorator'; export * from './route-constraints.decorator';
export * from './route-schema.decorator';

View File

@@ -0,0 +1,15 @@
import { SetMetadata } from '@nestjs/common';
import { FASTIFY_ROUTE_SCHEMA_METADATA } from '../constants';
import { FastifySchema } from 'fastify';
/**
* @publicApi
* Allows setting the schema for the route. Schema is an object that can contain the following properties:
* - body: JsonSchema
* - querystring or query: JsonSchema
* - params: JsonSchema
* - response: Record<HttpStatusCode, JsonSchema>
* @param schema See {@link https://fastify.dev/docs/latest/Reference/Routes/#routes-options}
*/
export const RouteSchema = (schema: FastifySchema) =>
SetMetadata(FASTIFY_ROUTE_SCHEMA_METADATA, schema);

View File

@@ -0,0 +1,17 @@
import { expect } from 'chai';
import { FASTIFY_ROUTE_SCHEMA_METADATA } from '../../constants';
import { RouteSchema } from '../../decorators/route-schema.decorator';
describe('@RouteSchema', () => {
const routeSchema = { body: 'testValue' };
class Test {
config;
@RouteSchema(routeSchema)
public static test() {}
}
it('should enhance method with expected fastify route schema', () => {
const path = Reflect.getMetadata(FASTIFY_ROUTE_SCHEMA_METADATA, Test.test);
expect(path).to.be.eql(routeSchema);
});
});