0
# Route Decorators
1
2
Specialized decorators for configuring Fastify-specific route behavior including constraints, schema validation, and configuration options.
3
4
## Capabilities
5
6
### RouteConfig Decorator
7
8
Sets Fastify route configuration metadata for enhanced route behavior and options.
9
10
```typescript { .api }
11
/**
12
* Decorator for setting Fastify route configuration
13
* Applies configuration options that will be passed to Fastify's route registration
14
* @param config - Route configuration object
15
*
16
* @see https://fastify.dev/docs/latest/Reference/Routes/#config
17
*/
18
function RouteConfig(config: any): MethodDecorator;
19
```
20
21
**Usage Examples:**
22
23
```typescript
24
import { Controller, Get } from '@nestjs/common';
25
import { RouteConfig } from '@nestjs/platform-fastify';
26
27
@Controller('users')
28
export class UsersController {
29
@Get(':id')
30
@RouteConfig({
31
// Custom route-specific configuration
32
rateLimit: {
33
max: 100,
34
timeWindow: '1 minute'
35
},
36
// Can include any Fastify route config
37
custom: {
38
authRequired: true,
39
roles: ['admin', 'user']
40
}
41
})
42
getUser(@Param('id') id: string) {
43
// Route handler implementation
44
return { id, name: 'John Doe' };
45
}
46
47
@Post()
48
@RouteConfig({
49
bodyLimit: 1024 * 1024, // 1MB limit for this route
50
preHandler: async (request, reply) => {
51
// Custom pre-handler logic
52
}
53
})
54
createUser(@Body() userData: any) {
55
// Route handler implementation
56
return userData;
57
}
58
}
59
```
60
61
### RouteConstraints Decorator
62
63
Sets Fastify route constraints for advanced routing based on request properties.
64
65
```typescript { .api }
66
/**
67
* Decorator for setting Fastify route constraints
68
* Enables advanced routing based on request properties like headers, host, etc.
69
* @param config - Route constraints configuration
70
*
71
* @see https://fastify.dev/docs/latest/Reference/Routes/#constraints
72
*/
73
function RouteConstraints(config: RouteShorthandOptions['config']): MethodDecorator;
74
```
75
76
**Usage Examples:**
77
78
```typescript
79
import { Controller, Get } from '@nestjs/common';
80
import { RouteConstraints } from '@nestjs/platform-fastify';
81
82
@Controller('api')
83
export class ApiController {
84
@Get('data')
85
@RouteConstraints({
86
// Route only matches for specific host
87
host: 'api.example.com'
88
})
89
getDataForApiDomain() {
90
return { message: 'API domain data' };
91
}
92
93
@Get('data')
94
@RouteConstraints({
95
// Route matches for different host
96
host: 'admin.example.com'
97
})
98
getDataForAdminDomain() {
99
return { message: 'Admin domain data' };
100
}
101
102
@Get('mobile-data')
103
@RouteConstraints({
104
// Route only matches for mobile user agents
105
headers: {
106
'user-agent': /Mobile|Android|iPhone/i
107
}
108
})
109
getMobileData() {
110
return { message: 'Mobile optimized data' };
111
}
112
113
@Get('version/:id')
114
@RouteConstraints({
115
// Route constraint based on custom logic
116
version: '2.0'
117
})
118
getVersionedData(@Param('id') id: string) {
119
return { id, version: '2.0', data: 'new format' };
120
}
121
}
122
```
123
124
### RouteSchema Decorator
125
126
Sets Fastify route schema for automatic request/response validation using JSON Schema.
127
128
```typescript { .api }
129
/**
130
* Decorator for setting Fastify route schema validation
131
* Enables automatic validation of request body, query parameters, route parameters, and response
132
* @param schema - JSON Schema definition for route validation
133
*
134
* @see https://fastify.dev/docs/latest/Reference/Routes/#routes-options
135
*/
136
function RouteSchema(schema: FastifySchema): MethodDecorator;
137
138
interface FastifySchema {
139
/** JSON Schema for request body validation */
140
body?: JsonSchema;
141
/** JSON Schema for query string validation */
142
querystring?: JsonSchema;
143
/** JSON Schema for query string validation (alias) */
144
query?: JsonSchema;
145
/** JSON Schema for route parameters validation */
146
params?: JsonSchema;
147
/** JSON Schema for response validation by status code */
148
response?: Record<number, JsonSchema>;
149
/** JSON Schema for request headers validation */
150
headers?: JsonSchema;
151
}
152
153
interface JsonSchema {
154
type?: string | string[];
155
properties?: Record<string, JsonSchema>;
156
required?: string[];
157
additionalProperties?: boolean;
158
items?: JsonSchema;
159
minimum?: number;
160
maximum?: number;
161
minLength?: number;
162
maxLength?: number;
163
pattern?: string;
164
enum?: any[];
165
format?: string;
166
[key: string]: any;
167
}
168
```
169
170
**Usage Examples:**
171
172
```typescript
173
import { Controller, Get, Post, Body, Param, Query } from '@nestjs/common';
174
import { RouteSchema } from '@nestjs/platform-fastify';
175
176
@Controller('products')
177
export class ProductsController {
178
@Get(':id')
179
@RouteSchema({
180
// Validate route parameters
181
params: {
182
type: 'object',
183
required: ['id'],
184
properties: {
185
id: {
186
type: 'string',
187
pattern: '^[0-9]+$' // Only numeric IDs
188
}
189
}
190
},
191
// Validate response format
192
response: {
193
200: {
194
type: 'object',
195
required: ['id', 'name', 'price'],
196
properties: {
197
id: { type: 'string' },
198
name: { type: 'string' },
199
price: { type: 'number', minimum: 0 },
200
description: { type: 'string' },
201
category: { type: 'string' }
202
}
203
},
204
404: {
205
type: 'object',
206
required: ['error', 'message'],
207
properties: {
208
error: { type: 'string' },
209
message: { type: 'string' }
210
}
211
}
212
}
213
})
214
getProduct(@Param('id') id: string) {
215
return {
216
id,
217
name: 'Product Name',
218
price: 29.99,
219
description: 'Product description',
220
category: 'electronics'
221
};
222
}
223
224
@Get()
225
@RouteSchema({
226
// Validate query parameters
227
querystring: {
228
type: 'object',
229
properties: {
230
page: {
231
type: 'integer',
232
minimum: 1,
233
default: 1
234
},
235
limit: {
236
type: 'integer',
237
minimum: 1,
238
maximum: 100,
239
default: 10
240
},
241
category: {
242
type: 'string',
243
enum: ['electronics', 'clothing', 'books', 'home']
244
},
245
minPrice: {
246
type: 'number',
247
minimum: 0
248
},
249
maxPrice: {
250
type: 'number',
251
minimum: 0
252
}
253
}
254
},
255
// Validate response
256
response: {
257
200: {
258
type: 'object',
259
required: ['products', 'total', 'page'],
260
properties: {
261
products: {
262
type: 'array',
263
items: {
264
type: 'object',
265
required: ['id', 'name', 'price'],
266
properties: {
267
id: { type: 'string' },
268
name: { type: 'string' },
269
price: { type: 'number' }
270
}
271
}
272
},
273
total: { type: 'integer' },
274
page: { type: 'integer' },
275
totalPages: { type: 'integer' }
276
}
277
}
278
}
279
})
280
getProducts(
281
@Query('page') page = 1,
282
@Query('limit') limit = 10,
283
@Query('category') category?: string,
284
@Query('minPrice') minPrice?: number,
285
@Query('maxPrice') maxPrice?: number
286
) {
287
return {
288
products: [],
289
total: 0,
290
page,
291
totalPages: 0
292
};
293
}
294
295
@Post()
296
@RouteSchema({
297
// Validate request body
298
body: {
299
type: 'object',
300
required: ['name', 'price', 'category'],
301
additionalProperties: false,
302
properties: {
303
name: {
304
type: 'string',
305
minLength: 1,
306
maxLength: 100
307
},
308
price: {
309
type: 'number',
310
minimum: 0,
311
maximum: 10000
312
},
313
category: {
314
type: 'string',
315
enum: ['electronics', 'clothing', 'books', 'home']
316
},
317
description: {
318
type: 'string',
319
maxLength: 1000
320
},
321
tags: {
322
type: 'array',
323
items: {
324
type: 'string',
325
minLength: 1
326
},
327
maxItems: 10
328
}
329
}
330
},
331
// Validate request headers
332
headers: {
333
type: 'object',
334
required: ['content-type'],
335
properties: {
336
'content-type': {
337
type: 'string',
338
enum: ['application/json']
339
}
340
}
341
},
342
// Validate response
343
response: {
344
201: {
345
type: 'object',
346
required: ['id', 'name', 'price', 'category', 'createdAt'],
347
properties: {
348
id: { type: 'string' },
349
name: { type: 'string' },
350
price: { type: 'number' },
351
category: { type: 'string' },
352
description: { type: 'string' },
353
tags: {
354
type: 'array',
355
items: { type: 'string' }
356
},
357
createdAt: { type: 'string', format: 'date-time' }
358
}
359
},
360
400: {
361
type: 'object',
362
required: ['error', 'message'],
363
properties: {
364
error: { type: 'string' },
365
message: { type: 'string' },
366
details: {
367
type: 'array',
368
items: {
369
type: 'object',
370
properties: {
371
field: { type: 'string' },
372
message: { type: 'string' }
373
}
374
}
375
}
376
}
377
}
378
}
379
})
380
createProduct(@Body() productData: any) {
381
return {
382
id: 'new-product-id',
383
...productData,
384
createdAt: new Date().toISOString()
385
};
386
}
387
}
388
```
389
390
## Metadata Constants
391
392
Constants used internally by the decorators for storing metadata.
393
394
```typescript { .api }
395
/** Metadata key for route configuration */
396
const FASTIFY_ROUTE_CONFIG_METADATA: string;
397
398
/** Metadata key for route constraints */
399
const FASTIFY_ROUTE_CONSTRAINTS_METADATA: string;
400
401
/** Metadata key for route schema */
402
const FASTIFY_ROUTE_SCHEMA_METADATA: string;
403
```
404
405
These constants are used internally by the decorators and the FastifyAdapter to retrieve and apply the metadata to routes. They are exported for advanced use cases where manual metadata manipulation might be needed.
406
407
## Integration with NestJS
408
409
The decorators work seamlessly with standard NestJS decorators and can be combined for comprehensive route configuration:
410
411
```typescript
412
import { Controller, Get, Post, UseGuards, UseInterceptors } from '@nestjs/common';
413
import { RouteConfig, RouteConstraints, RouteSchema } from '@nestjs/platform-fastify';
414
import { AuthGuard } from './auth.guard';
415
import { LoggingInterceptor } from './logging.interceptor';
416
417
@Controller('secure')
418
@UseGuards(AuthGuard)
419
@UseInterceptors(LoggingInterceptor)
420
export class SecureController {
421
@Get('data')
422
@RouteConfig({
423
rateLimit: { max: 10, timeWindow: '1 minute' }
424
})
425
@RouteConstraints({
426
headers: { 'x-api-key': /^[a-f0-9]{32}$/ }
427
})
428
@RouteSchema({
429
headers: {
430
type: 'object',
431
required: ['x-api-key'],
432
properties: {
433
'x-api-key': { type: 'string', pattern: '^[a-f0-9]{32}$' }
434
}
435
},
436
response: {
437
200: {
438
type: 'object',
439
properties: {
440
data: { type: 'array' },
441
timestamp: { type: 'string' }
442
}
443
}
444
}
445
})
446
getSecureData() {
447
return {
448
data: ['sensitive', 'information'],
449
timestamp: new Date().toISOString()
450
};
451
}
452
}
453
```