fastify 4.0.3 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.eslintrc +1 -0
  2. package/README.md +13 -14
  3. package/docs/Guides/Database.md +7 -7
  4. package/docs/Guides/Delay-Accepting-Requests.md +1 -1
  5. package/docs/Guides/Ecosystem.md +29 -16
  6. package/docs/Guides/Migration-Guide-V4.md +86 -1
  7. package/docs/Guides/Plugins-Guide.md +5 -0
  8. package/docs/Guides/Serverless.md +23 -10
  9. package/docs/Reference/Hooks.md +52 -0
  10. package/docs/Reference/Plugins.md +1 -1
  11. package/docs/Reference/Server.md +1 -1
  12. package/docs/Reference/Type-Providers.md +3 -17
  13. package/docs/Reference/TypeScript.md +65 -28
  14. package/docs/Reference/Validation-and-Serialization.md +11 -0
  15. package/docs/index.md +1 -1
  16. package/fastify.d.ts +3 -3
  17. package/fastify.js +19 -19
  18. package/integration/server.js +27 -0
  19. package/integration/test.sh +23 -0
  20. package/lib/context.js +5 -2
  21. package/lib/error-serializer.js +24 -27
  22. package/lib/handleRequest.js +1 -1
  23. package/lib/reply.js +22 -21
  24. package/lib/route.js +39 -29
  25. package/lib/symbols.js +2 -1
  26. package/lib/validation.js +2 -0
  27. package/package.json +10 -10
  28. package/test/404s.test.js +2 -2
  29. package/test/build/error-serializer.test.js +9 -2
  30. package/test/hooks.test.js +21 -0
  31. package/test/internals/reply.test.js +12 -0
  32. package/test/pretty-print.test.js +3 -3
  33. package/test/reply-error.test.js +1 -1
  34. package/test/schema-feature.test.js +2 -2
  35. package/test/schema-validation.test.js +71 -0
  36. package/test/stream.test.js +1 -1
  37. package/test/types/fastify.test-d.ts +24 -2
  38. package/test/types/instance.test-d.ts +5 -2
  39. package/test/types/register.test-d.ts +77 -2
  40. package/test/types/request.test-d.ts +8 -4
  41. package/test/types/type-provider.test-d.ts +11 -2
  42. package/test/validation-error-handling.test.js +38 -1
  43. package/types/instance.d.ts +59 -91
  44. package/types/register.d.ts +9 -7
  45. package/types/route.d.ts +10 -12
  46. package/types/schema.d.ts +5 -2
  47. package/types/type-provider.d.ts +12 -5
@@ -49,7 +49,7 @@ interface RequestData extends RequestGenericInterface {
49
49
  type Handler = RouteHandler<RequestData>
50
50
 
51
51
  type CustomRequest = FastifyRequest<{
52
- Body: RequestBody;
52
+ Body: RequestBody | undefined;
53
53
  Querystring: RequestQuerystring;
54
54
  Params: RequestParams;
55
55
  Headers: RequestHeaders;
@@ -85,7 +85,7 @@ const getHandler: RouteHandler = function (request, _reply) {
85
85
  expectType<FastifyInstance>(request.server)
86
86
  }
87
87
 
88
- const getHandlerWithCustomLogger: RouteHandlerMethod<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, ResolveFastifyReplyReturnType<FastifyTypeProviderDefault, FastifySchema, RouteGenericInterface>, ResolveFastifyRequestType<FastifyTypeProviderDefault, FastifySchema, RouteGenericInterface>, CustomLoggerInterface> = function (request, _reply) {
88
+ const getHandlerWithCustomLogger: RouteHandlerMethod<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, ResolveFastifyRequestType<FastifyTypeProviderDefault, FastifySchema, RouteGenericInterface>, CustomLoggerInterface> = function (request, _reply) {
89
89
  expectType<CustomLoggerInterface>(request.log)
90
90
  }
91
91
 
@@ -104,11 +104,15 @@ const postHandler: Handler = function (request) {
104
104
  }
105
105
 
106
106
  function putHandler (request: CustomRequest, reply: FastifyReply) {
107
- expectType<RequestBody>(request.body)
107
+ expectType<RequestBody | undefined>(request.body)
108
108
  expectType<RequestParams>(request.params)
109
109
  expectType<RequestHeaders & RawRequestDefaultExpression['headers']>(request.headers)
110
110
  expectType<RequestQuerystring>(request.query)
111
- expectType<string>(request.body.content)
111
+ if (typeof request.body === 'undefined') {
112
+ expectType<undefined>(request.body)
113
+ } else {
114
+ expectType<string>(request.body.content)
115
+ }
112
116
  expectType<string>(request.query.from)
113
117
  expectType<number>(request.params.id)
114
118
  expectType<string>(request.headers['x-foobar'])
@@ -298,7 +298,7 @@ expectError(server.withTypeProvider<TypeBoxProvider>().get(
298
298
  }
299
299
  }
300
300
  },
301
- async (_, res): Promise<RouteHandlerMethod<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, TypeBoxProvider>> => {
301
+ async (_, res) => {
302
302
  return false
303
303
  }
304
304
  ))
@@ -384,11 +384,20 @@ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
384
384
  } as const
385
385
  }
386
386
  },
387
- async (_, res): Promise<RouteHandlerMethod<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, TypeBoxProvider>> => {
387
+ async (_, res) => {
388
388
  return false
389
389
  }
390
390
  ))
391
391
 
392
+ // https://github.com/fastify/fastify/issues/4088
393
+ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get('/', {
394
+ schema: {
395
+ response: { type: 'string' }
396
+ } as const
397
+ }, (_, res) => {
398
+ return { foo: 555 }
399
+ }))
400
+
392
401
  // -------------------------------------------------------------------
393
402
  // Reply Type Override
394
403
  // -------------------------------------------------------------------
@@ -97,6 +97,38 @@ test('should be able to use setErrorHandler specify custom validation error', t
97
97
  })
98
98
  })
99
99
 
100
+ test('validation error has 400 statusCode set', t => {
101
+ t.plan(3)
102
+
103
+ const fastify = Fastify()
104
+
105
+ fastify.setErrorHandler((error, request, reply) => {
106
+ const errorResponse = {
107
+ message: error.message,
108
+ statusCode: error.statusCode || 500
109
+ }
110
+
111
+ reply.code(errorResponse.statusCode).send(errorResponse)
112
+ })
113
+
114
+ fastify.post('/', { schema }, echoBody)
115
+
116
+ fastify.inject({
117
+ method: 'POST',
118
+ payload: {
119
+ hello: 'michelangelo'
120
+ },
121
+ url: '/'
122
+ }, (err, res) => {
123
+ t.error(err)
124
+ t.same(res.json(), {
125
+ statusCode: 400,
126
+ message: "body must have required property 'name'"
127
+ })
128
+ t.equal(res.statusCode, 400)
129
+ })
130
+ })
131
+
100
132
  test('error inside custom error handler should have validationContext', t => {
101
133
  t.plan(1)
102
134
 
@@ -462,12 +494,17 @@ test('the custom error formatter context must be the server instance in options'
462
494
  })
463
495
 
464
496
  test('should call custom error formatter', t => {
465
- t.plan(6)
497
+ t.plan(9)
466
498
 
467
499
  const fastify = Fastify({
468
500
  schemaErrorFormatter: (errors, dataVar) => {
469
501
  t.equal(errors.length, 1)
470
502
  t.equal(errors[0].message, "must have required property 'name'")
503
+ t.equal(errors[0].keyword, 'required')
504
+ t.equal(errors[0].schemaPath, '#/required')
505
+ t.same(errors[0].params, {
506
+ missingProperty: 'name'
507
+ })
471
508
  t.equal(dataVar, 'body')
472
509
  return new Error('my error')
473
510
  }
@@ -1,6 +1,6 @@
1
- import * as http from 'http'
2
1
  import { FastifyError } from '@fastify/error'
3
2
  import { ConstraintStrategy, HTTPVersion } from 'find-my-way'
3
+ import * as http from 'http'
4
4
  import { CallbackFunc as LightMyRequestCallback, Chain as LightMyRequestChain, InjectOptions, Response as LightMyRequestResponse } from 'light-my-request'
5
5
  import { AddContentTypeParser, ConstructorAction, FastifyBodyParser, getDefaultJsonParser, hasContentTypeParser, ProtoAction, removeAllContentTypeParsers, removeContentTypeParser } from './content-type-parser'
6
6
  import { onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler } from './hooks'
@@ -30,6 +30,52 @@ export interface PrintRoutesOptions {
30
30
  includeHooks?: boolean
31
31
  }
32
32
 
33
+ export interface FastifyListenOptions {
34
+ /**
35
+ * Default to `0` (picks the first available open port).
36
+ */
37
+ port?: number;
38
+ /**
39
+ * Default to `localhost`.
40
+ */
41
+ host?: string;
42
+ /**
43
+ * Will be ignored if `port` is specified.
44
+ * @see [Identifying paths for IPC connections](https://nodejs.org/api/net.html#identifying-paths-for-ipc-connections).
45
+ */
46
+ path?: string;
47
+ /**
48
+ * Specify the maximum length of the queue of pending connections.
49
+ * The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux.
50
+ * Default to `511`.
51
+ */
52
+ backlog?: number;
53
+ /**
54
+ * Default to `false`.
55
+ */
56
+ exclusive?: boolean;
57
+ /**
58
+ * For IPC servers makes the pipe readable for all users.
59
+ * Default to `false`.
60
+ */
61
+ readableAll?: boolean;
62
+ /**
63
+ * For IPC servers makes the pipe writable for all users.
64
+ * Default to `false`.
65
+ */
66
+ writableAll?: boolean;
67
+ /**
68
+ * For TCP servers, setting `ipv6Only` to `true` will disable dual-stack support, i.e., binding to host `::` won't make `0.0.0.0` be bound.
69
+ * Default to `false`.
70
+ */
71
+ ipv6Only?: boolean;
72
+ /**
73
+ * An AbortSignal that may be used to close a listening server.
74
+ * @since This option is available only in Node.js v15.6.0 and greater
75
+ */
76
+ signal?: AbortSignal;
77
+ }
78
+
33
79
  type NotInInterface<Key, _Interface> = Key extends keyof _Interface ? never : Key
34
80
  type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server ? HTTPVersion.V1 : HTTPVersion.V2
35
81
 
@@ -93,96 +139,8 @@ export interface FastifyInstance<
93
139
  inject(opts: InjectOptions | string): Promise<LightMyRequestResponse>;
94
140
  inject(): LightMyRequestChain;
95
141
 
96
- listen(opts: {
97
- /**
98
- * Default to `0` (picks the first available open port).
99
- */
100
- port?: number;
101
- /**
102
- * Default to `localhost`.
103
- */
104
- host?: string;
105
- /**
106
- * Will be ignored if `port` is specified.
107
- * @see [Identifying paths for IPC connections](https://nodejs.org/api/net.html#identifying-paths-for-ipc-connections).
108
- */
109
- path?: string;
110
- /**
111
- * Specify the maximum length of the queue of pending connections.
112
- * The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux.
113
- * Default to `511`.
114
- */
115
- backlog?: number;
116
- /**
117
- * Default to `false`.
118
- */
119
- exclusive?: boolean;
120
- /**
121
- * For IPC servers makes the pipe readable for all users.
122
- * Default to `false`.
123
- */
124
- readableAll?: boolean;
125
- /**
126
- * For IPC servers makes the pipe writable for all users.
127
- * Default to `false`.
128
- */
129
- writableAll?: boolean;
130
- /**
131
- * For TCP servers, setting `ipv6Only` to `true` will disable dual-stack support, i.e., binding to host `::` won't make `0.0.0.0` be bound.
132
- * Default to `false`.
133
- */
134
- ipv6Only?: boolean;
135
- /**
136
- * An AbortSignal that may be used to close a listening server.
137
- * @since This option is available only in Node.js v15.6.0 and greater
138
- */
139
- signal?: AbortSignal;
140
- }, callback: (err: Error|null, address: string) => void): void;
141
- listen(opts?: {
142
- /**
143
- * Default to `0` (picks the first available open port).
144
- */
145
- port?: number;
146
- /**
147
- * Default to `localhost`.
148
- */
149
- host?: string;
150
- /**
151
- * Will be ignored if `port` is specified.
152
- * @see [Identifying paths for IPC connections](https://nodejs.org/api/net.html#identifying-paths-for-ipc-connections).
153
- */
154
- path?: string;
155
- /**
156
- * Specify the maximum length of the queue of pending connections.
157
- * The actual length will be determined by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux.
158
- * Default to `511`.
159
- */
160
- backlog?: number;
161
- /**
162
- * Default to `false`.
163
- */
164
- exclusive?: boolean;
165
- /**
166
- * For IPC servers makes the pipe readable for all users.
167
- * Default to `false`.
168
- */
169
- readableAll?: boolean;
170
- /**
171
- * For IPC servers makes the pipe writable for all users.
172
- * Default to `false`.
173
- */
174
- writableAll?: boolean;
175
- /**
176
- * For TCP servers, setting `ipv6Only` to `true` will disable dual-stack support, i.e., binding to host `::` won't make `0.0.0.0` be bound.
177
- * Default to `false`.
178
- */
179
- ipv6Only?: boolean;
180
- /**
181
- * An AbortSignal that may be used to close a listening server.
182
- * @since This option is available only in Node.js v15.6.0 and greater
183
- */
184
- signal?: AbortSignal;
185
- }): Promise<string>;
142
+ listen(opts: FastifyListenOptions, callback: (err: Error | null, address: string) => void): void;
143
+ listen(opts?: FastifyListenOptions): Promise<string>;
186
144
  listen(callback: (err: Error | null, address: string) => void): void;
187
145
 
188
146
  /**
@@ -550,11 +508,21 @@ export interface FastifyInstance<
550
508
  handler: (this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>, error: TError, request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>, reply: FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfigDefault, SchemaCompiler, TypeProvider>) => any | Promise<any>
551
509
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
552
510
 
511
+ /**
512
+ * Fastify schema validator for all routes.
513
+ */
514
+ validatorCompiler: FastifySchemaCompiler<any> | undefined;
515
+
553
516
  /**
554
517
  * Set the schema validator for all routes.
555
518
  */
556
519
  setValidatorCompiler<T = FastifySchema>(schemaCompiler: FastifySchemaCompiler<T>): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
557
520
 
521
+ /**
522
+ * Fastify schema serializer for all routes.
523
+ */
524
+ serializerCompiler: FastifySerializerCompiler<any> | undefined;
525
+
558
526
  /**
559
527
  * Set the schema serializer for all routes.
560
528
  */
@@ -1,6 +1,8 @@
1
1
  import { FastifyPluginOptions, FastifyPluginCallback, FastifyPluginAsync } from './plugin'
2
2
  import { LogLevel } from './logger'
3
3
  import { FastifyInstance } from './instance'
4
+ import { RawServerBase } from './utils'
5
+ import { FastifyTypeProvider, RawServerDefault } from '../fastify'
4
6
 
5
7
  export interface RegisterOptions {
6
8
  prefix?: string;
@@ -15,17 +17,17 @@ export type FastifyRegisterOptions<Options> = (RegisterOptions & Options) | ((in
15
17
  *
16
18
  * Function for adding a plugin to fastify. The options are inferred from the passed in FastifyPlugin parameter.
17
19
  */
18
- export interface FastifyRegister<T = void> {
19
- <Options extends FastifyPluginOptions>(
20
- plugin: FastifyPluginCallback<Options>,
20
+ export interface FastifyRegister<T = void, RawServer extends RawServerBase = RawServerDefault, TypeProviderDefault extends FastifyTypeProvider = FastifyTypeProvider> {
21
+ <Options extends FastifyPluginOptions, Server extends RawServerBase = RawServer, TypeProvider extends FastifyTypeProvider = TypeProviderDefault>(
22
+ plugin: FastifyPluginCallback<Options, Server, TypeProvider>,
21
23
  opts?: FastifyRegisterOptions<Options>
22
24
  ): T;
23
- <Options extends FastifyPluginOptions>(
24
- plugin: FastifyPluginAsync<Options>,
25
+ <Options extends FastifyPluginOptions, Server extends RawServerBase = RawServer, TypeProvider extends FastifyTypeProvider = TypeProviderDefault>(
26
+ plugin: FastifyPluginAsync<Options, Server, TypeProvider>,
25
27
  opts?: FastifyRegisterOptions<Options>
26
28
  ): T;
27
- <Options extends FastifyPluginOptions>(
28
- plugin: FastifyPluginCallback<Options> | FastifyPluginAsync<Options> | Promise<{ default: FastifyPluginCallback<Options> }> | Promise<{ default: FastifyPluginAsync<Options> }>,
29
+ <Options extends FastifyPluginOptions, Server extends RawServerBase = RawServer, TypeProvider extends FastifyTypeProvider = TypeProviderDefault>(
30
+ plugin: FastifyPluginCallback<Options, Server, TypeProvider> | FastifyPluginAsync<Options, Server, TypeProvider> | Promise<{ default: FastifyPluginCallback<Options, Server, TypeProvider> }> | Promise<{ default: FastifyPluginAsync<Options, Server, TypeProvider> }>,
29
31
  opts?: FastifyRegisterOptions<Options>
30
32
  ): T;
31
33
  }
package/types/route.d.ts CHANGED
@@ -69,14 +69,14 @@ export type RouteHandlerMethod<
69
69
  ContextConfig = ContextConfigDefault,
70
70
  SchemaCompiler extends FastifySchema = FastifySchema,
71
71
  TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
72
- ReturnType = ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>,
73
72
  RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>,
74
73
  Logger extends FastifyLoggerInstance = FastifyLoggerInstance
75
74
  > = (
76
75
  this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>,
77
76
  request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, RequestType, Logger>,
78
77
  reply: FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>
79
- ) => ReturnType
78
+ // This return type used to be a generic type argument. Due to TypeScript's inference of return types, this rendered returns unchecked.
79
+ ) => ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>
80
80
 
81
81
  /**
82
82
  * Shorthand options including the handler function property
@@ -89,11 +89,10 @@ export interface RouteShorthandOptionsWithHandler<
89
89
  ContextConfig = ContextConfigDefault,
90
90
  SchemaCompiler = FastifySchema,
91
91
  TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
92
- ReturnType = ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>,
93
92
  RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>,
94
93
  Logger extends FastifyLoggerInstance = FastifyLoggerInstance
95
94
  > extends RouteShorthandOptions<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger> {
96
- handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReturnType, RequestType, Logger>;
95
+ handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger>;
97
96
  }
98
97
 
99
98
  /**
@@ -105,18 +104,18 @@ export interface RouteShorthandMethod<
105
104
  RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
106
105
  TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
107
106
  > {
108
- <RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema, ReturnType = ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>, RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>, Logger extends FastifyLoggerInstance = FastifyLoggerInstance>(
107
+ <RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema, RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>, Logger extends FastifyLoggerInstance = FastifyLoggerInstance>(
109
108
  path: string,
110
109
  opts: RouteShorthandOptions<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger>,
111
- handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReturnType, RequestType, Logger>
110
+ handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger>
112
111
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
113
- <RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema, ReturnType = ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>, RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>, Logger extends FastifyLoggerInstance = FastifyLoggerInstance>(
112
+ <RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema, RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>, Logger extends FastifyLoggerInstance = FastifyLoggerInstance>(
114
113
  path: string,
115
- handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReturnType, RequestType, Logger>
114
+ handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger>
116
115
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
117
- <RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema, ReturnType = ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>, RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>, Logger extends FastifyLoggerInstance = FastifyLoggerInstance>(
116
+ <RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema, RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>, Logger extends FastifyLoggerInstance = FastifyLoggerInstance>(
118
117
  path: string,
119
- opts: RouteShorthandOptionsWithHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReturnType, RequestType, Logger>
118
+ opts: RouteShorthandOptionsWithHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger>
120
119
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
121
120
  }
122
121
 
@@ -131,13 +130,12 @@ export interface RouteOptions<
131
130
  ContextConfig = ContextConfigDefault,
132
131
  SchemaCompiler = FastifySchema,
133
132
  TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
134
- ReturnType = ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>,
135
133
  RequestType extends FastifyRequestType = ResolveFastifyRequestType<TypeProvider, SchemaCompiler, RouteGeneric>,
136
134
  Logger extends FastifyLoggerInstance = FastifyLoggerInstance
137
135
  > extends RouteShorthandOptions<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger> {
138
136
  method: HTTPMethods | HTTPMethods[];
139
137
  url: string;
140
- handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReturnType, RequestType, Logger>;
138
+ handler: RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, RequestType, Logger>;
141
139
  }
142
140
 
143
141
  export type RouteHandler<
package/types/schema.d.ts CHANGED
@@ -23,8 +23,11 @@ export interface FastifyRouteSchemaDef<T> {
23
23
  }
24
24
 
25
25
  export interface FastifySchemaValidationError {
26
- message?: string;
26
+ keyword: string;
27
27
  instancePath: string;
28
+ schemaPath: string;
29
+ params: Record<string, string | string[]>;
30
+ message?: string;
28
31
  }
29
32
 
30
33
  export interface FastifyValidationResult {
@@ -41,7 +44,7 @@ export type FastifySerializerCompiler<T> = (routeSchema: FastifyRouteSchemaDef<T
41
44
 
42
45
  export interface FastifySchemaControllerOptions{
43
46
  bucket?: (parentSchemas?: unknown) => {
44
- addSchema(schema: unknown): FastifyInstance;
47
+ add(schema: unknown): FastifyInstance;
45
48
  getSchema(schemaId: string): unknown;
46
49
  getSchemas(): Record<string, unknown>;
47
50
  };
@@ -21,17 +21,24 @@ export type CallTypeProvider<F extends FastifyTypeProvider, I> = (F & { input: I
21
21
  // -----------------------------------------------------------------------------------------------
22
22
 
23
23
  // Used to map undefined SchemaCompiler properties to unknown
24
- type UndefinedToUnknown<T> = T extends undefined ? unknown : T
24
+ // Without brackets, UndefinedToUnknown<undefined | null> => unknown
25
+ type UndefinedToUnknown<T> = [T] extends [undefined] ? unknown : T
26
+
27
+ // union-aware keyof operator
28
+ // keyof ({ a: number} | { b: number}) => never
29
+ // KeysOf<{a: number} | {b: number}> => "a" | "b"
30
+ // this exists to allow users to override faulty type-provider logic.
31
+ type KeysOf<T> = T extends any ? keyof T : never
25
32
 
26
33
  // Resolves Request types either from generic argument or Type Provider.
27
34
  type ResolveRequestParams<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema, RouteGeneric extends RouteGenericInterface> =
28
- UndefinedToUnknown<keyof RouteGeneric['Params'] extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['params']> : RouteGeneric['Params']>
35
+ UndefinedToUnknown<KeysOf<RouteGeneric['Params']> extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['params']> : RouteGeneric['Params']>
29
36
  type ResolveRequestQuerystring<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema, RouteGeneric extends RouteGenericInterface> =
30
- UndefinedToUnknown<keyof RouteGeneric['Querystring'] extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['querystring']> : RouteGeneric['Querystring']>
37
+ UndefinedToUnknown<KeysOf<RouteGeneric['Querystring']> extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['querystring']> : RouteGeneric['Querystring']>
31
38
  type ResolveRequestHeaders<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema, RouteGeneric extends RouteGenericInterface> =
32
- UndefinedToUnknown<keyof RouteGeneric['Headers'] extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['headers']> : RouteGeneric['Headers']>
39
+ UndefinedToUnknown<KeysOf<RouteGeneric['Headers']> extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['headers']> : RouteGeneric['Headers']>
33
40
  type ResolveRequestBody<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema, RouteGeneric extends RouteGenericInterface> =
34
- UndefinedToUnknown<keyof RouteGeneric['Body'] extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['body']> : RouteGeneric['Body']>
41
+ UndefinedToUnknown<KeysOf<RouteGeneric['Body']> extends never ? CallTypeProvider<TypeProvider, SchemaCompiler['body']> : RouteGeneric['Body']>
35
42
 
36
43
  // The target request type. This type is inferenced on fastify 'requests' via generic argument assignment
37
44
  export interface FastifyRequestType<Params = unknown, Querystring = unknown, Headers = unknown, Body = unknown> {