fastify 5.6.1 → 5.6.2

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 (61) hide show
  1. package/build/build-validation.js +1 -1
  2. package/build/sync-version.js +1 -0
  3. package/docs/Guides/Ecosystem.md +5 -0
  4. package/docs/Guides/Fluent-Schema.md +2 -2
  5. package/docs/Reference/Encapsulation.md +5 -1
  6. package/docs/Reference/Plugins.md +11 -2
  7. package/docs/Reference/Reply.md +3 -0
  8. package/docs/Reference/Server.md +32 -0
  9. package/docs/Reference/Type-Providers.md +2 -2
  10. package/eslint.config.js +18 -2
  11. package/fastify.d.ts +1 -1
  12. package/fastify.js +179 -169
  13. package/lib/{contentTypeParser.js → content-type-parser.js} +2 -1
  14. package/lib/error-handler.js +2 -2
  15. package/lib/{fourOhFour.js → four-oh-four.js} +4 -2
  16. package/lib/{handleRequest.js → handle-request.js} +1 -1
  17. package/lib/{headRoute.js → head-route.js} +13 -1
  18. package/lib/{initialConfigValidation.js → initial-config-validation.js} +1 -1
  19. package/lib/{pluginOverride.js → plugin-override.js} +2 -2
  20. package/lib/{pluginUtils.js → plugin-utils.js} +2 -2
  21. package/lib/reply.js +5 -3
  22. package/lib/request.js +5 -0
  23. package/lib/route.js +20 -9
  24. package/lib/server.js +38 -5
  25. package/lib/validation.js +9 -1
  26. package/package.json +8 -8
  27. package/test/500s.test.js +191 -0
  28. package/test/child-logger-factory.test.js +3 -3
  29. package/test/content-parser.test.js +2 -1
  30. package/test/diagnostics-channel/error-before-handler.test.js +1 -1
  31. package/test/internals/content-type-parser.test.js +2 -2
  32. package/test/internals/handle-request.test.js +2 -2
  33. package/test/internals/initial-config.test.js +1 -1
  34. package/test/internals/plugin.test.js +2 -2
  35. package/test/internals/reply.test.js +22 -3
  36. package/test/internals/req-id-gen-factory.test.js +1 -1
  37. package/test/promises.test.js +3 -3
  38. package/test/reply-web-stream-locked.test.js +37 -0
  39. package/test/request-error.test.js +116 -0
  40. package/test/route.6.test.js +20 -1
  41. package/test/route.7.test.js +49 -0
  42. package/test/schema-validation.test.js +27 -4
  43. package/test/server.test.js +22 -4
  44. package/test/stream.5.test.js +3 -3
  45. package/test/types/fastify.test-d.ts +70 -18
  46. package/test/types/hooks.test-d.ts +6 -1
  47. package/test/types/instance.test-d.ts +35 -15
  48. package/test/types/logger.test-d.ts +18 -6
  49. package/test/types/plugin.test-d.ts +24 -6
  50. package/test/types/register.test-d.ts +108 -33
  51. package/test/types/reply.test-d.ts +23 -6
  52. package/test/types/request.test-d.ts +25 -6
  53. package/test/types/route.test-d.ts +10 -1
  54. package/test/validation-error-handling.test.js +68 -1
  55. package/test/wrap-thenable.test.js +1 -1
  56. package/types/instance.d.ts +2 -2
  57. package/test/check.test.js +0 -219
  58. /package/lib/{configValidator.js → config-validator.js} +0 -0
  59. /package/lib/{reqIdGenFactory.js → req-id-gen-factory.js} +0 -0
  60. /package/lib/{wrapThenable.js → wrap-thenable.js} +0 -0
  61. /package/types/{serverFactory.d.ts → server-factory.d.ts} +0 -0
@@ -21,8 +21,15 @@ const testPluginOptsAsync: FastifyPluginAsync<TestOptions> = async function (ins
21
21
  expectType<TestOptions>(opts)
22
22
  }
23
23
 
24
- const testPluginOptsWithType = (instance: FastifyInstance, opts: FastifyPluginOptions, done: (error?: FastifyError) => void) => { }
25
- const testPluginOptsWithTypeAsync = async (instance: FastifyInstance, opts: FastifyPluginOptions) => { }
24
+ const testPluginOptsWithType = (
25
+ instance: FastifyInstance,
26
+ opts: FastifyPluginOptions,
27
+ done: (error?: FastifyError) => void
28
+ ) => { }
29
+ const testPluginOptsWithTypeAsync = async (
30
+ instance: FastifyInstance,
31
+ opts: FastifyPluginOptions
32
+ ) => { }
26
33
 
27
34
  expectError(fastify().register(testPluginOpts, {})) // error because missing required options from generic declaration
28
35
  expectError(fastify().register(testPluginOptsAsync, {})) // error because missing required options from generic declaration
@@ -43,16 +50,27 @@ expectAssignable<FastifyInstance>(fastify().register(testPluginCallback, {}))
43
50
  const testPluginAsync: FastifyPluginAsync = async function (instance, opts) { }
44
51
  expectAssignable<FastifyInstance>(fastify().register(testPluginAsync, {}))
45
52
 
46
- expectAssignable<FastifyInstance>(fastify().register(function (instance, opts): Promise<void> { return Promise.resolve() }))
53
+ expectAssignable<FastifyInstance>(
54
+ fastify().register(function (instance, opts): Promise<void> { return Promise.resolve() })
55
+ )
47
56
  expectAssignable<FastifyInstance>(fastify().register(async function (instance, opts) { }, () => { }))
48
57
  expectAssignable<FastifyInstance>(fastify().register(async function (instance, opts) { }, { logLevel: 'info', prefix: 'foobar' }))
49
58
 
50
59
  expectError(fastify().register(function (instance, opts, done) { }, { ...testOptions, logLevel: '' })) // must use a valid logLevel
51
60
 
52
61
  const httpsServer = fastify({ https: {} })
53
- expectError<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> & Promise<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>>(httpsServer)
54
- expectAssignable<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> & PromiseLike<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>>(httpsServer)
55
- expectType<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> & SafePromiseLike<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>>(httpsServer)
62
+ expectError<
63
+ FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> &
64
+ Promise<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>
65
+ >(httpsServer)
66
+ expectAssignable<
67
+ FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> &
68
+ PromiseLike<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>
69
+ >(httpsServer)
70
+ expectType<
71
+ FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> &
72
+ SafePromiseLike<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>
73
+ >(httpsServer)
56
74
 
57
75
  // Chainable
58
76
  httpsServer
@@ -9,7 +9,11 @@ const testPluginAsync: FastifyPluginAsync = async function (instance, opts) { }
9
9
  const testPluginOpts: FastifyPluginCallback = function (instance, opts, done) { }
10
10
  const testPluginOptsAsync: FastifyPluginAsync = async function (instance, opts) { }
11
11
 
12
- const testPluginOptsWithType = (instance: FastifyInstance, opts: FastifyPluginOptions, done: (error?: FastifyError) => void) => { }
12
+ const testPluginOptsWithType = (
13
+ instance: FastifyInstance,
14
+ opts: FastifyPluginOptions,
15
+ done: (error?: FastifyError) => void
16
+ ) => { }
13
17
  const testPluginOptsWithTypeAsync = async (instance: FastifyInstance, opts: FastifyPluginOptions) => { }
14
18
 
15
19
  interface TestOptions extends FastifyPluginOptions {
@@ -46,8 +50,15 @@ const serverWithHttp2 = fastify({ http2: true })
46
50
  type ServerWithHttp2 = FastifyInstance<Http2Server, Http2ServerRequest, Http2ServerResponse>
47
51
  const testPluginWithHttp2: FastifyPluginCallback<TestOptions, Http2Server> = function (instance, opts, done) { }
48
52
  const testPluginWithHttp2Async: FastifyPluginAsync<TestOptions, Http2Server> = async function (instance, opts) { }
49
- const testPluginWithHttp2WithType = (instance: ServerWithHttp2, opts: FastifyPluginOptions, done: (error?: FastifyError) => void) => { }
50
- const testPluginWithHttp2WithTypeAsync = async (instance: ServerWithHttp2, opts: FastifyPluginOptions) => { }
53
+ const testPluginWithHttp2WithType = (
54
+ instance: ServerWithHttp2,
55
+ opts: FastifyPluginOptions,
56
+ done: (error?: FastifyError) => void
57
+ ) => { }
58
+ const testPluginWithHttp2WithTypeAsync = async (
59
+ instance: ServerWithHttp2,
60
+ opts: FastifyPluginOptions
61
+ ) => { }
51
62
  const testOptions: TestOptions = {
52
63
  option1: 'a',
53
64
  option2: false
@@ -82,11 +93,32 @@ expectAssignable<ServerWithHttp2>(serverWithHttp2.register(async (instance: Serv
82
93
  // With Type Provider
83
94
  type TestTypeProvider = { schema: 'test', validator: 'test', serializer: 'test' }
84
95
  const serverWithTypeProvider = fastify().withTypeProvider<TestTypeProvider>()
85
- type ServerWithTypeProvider = FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance, TestTypeProvider>
86
- const testPluginWithTypeProvider: FastifyPluginCallback<TestOptions, RawServerDefault, TestTypeProvider> = function (instance, opts, done) { }
87
- const testPluginWithTypeProviderAsync: FastifyPluginAsync<TestOptions, RawServerDefault, TestTypeProvider> = async function (instance, opts) { }
88
- const testPluginWithTypeProviderWithType = (instance: ServerWithTypeProvider, opts: FastifyPluginOptions, done: (error?: FastifyError) => void) => { }
89
- const testPluginWithTypeProviderWithTypeAsync = async (instance: ServerWithTypeProvider, opts: FastifyPluginOptions) => { }
96
+ type ServerWithTypeProvider = FastifyInstance<
97
+ Server,
98
+ IncomingMessage,
99
+ ServerResponse,
100
+ FastifyLoggerInstance,
101
+ TestTypeProvider
102
+ >
103
+ const testPluginWithTypeProvider: FastifyPluginCallback<
104
+ TestOptions,
105
+ RawServerDefault,
106
+ TestTypeProvider
107
+ > = function (instance, opts, done) { }
108
+ const testPluginWithTypeProviderAsync: FastifyPluginAsync<
109
+ TestOptions,
110
+ RawServerDefault,
111
+ TestTypeProvider
112
+ > = async function (instance, opts) { }
113
+ const testPluginWithTypeProviderWithType = (
114
+ instance: ServerWithTypeProvider,
115
+ opts: FastifyPluginOptions,
116
+ done: (error?: FastifyError) => void
117
+ ) => { }
118
+ const testPluginWithTypeProviderWithTypeAsync = async (
119
+ instance: ServerWithTypeProvider,
120
+ opts: FastifyPluginOptions
121
+ ) => { }
90
122
  expectAssignable<ServerWithTypeProvider>(serverWithTypeProvider.register(testPluginCallback))
91
123
  expectAssignable<ServerWithTypeProvider>(serverWithTypeProvider.register(testPluginAsync))
92
124
  expectAssignable<ServerWithTypeProvider>(serverWithTypeProvider.register(testPluginOpts))
@@ -129,34 +161,77 @@ const customLogger = {
129
161
  const serverWithTypeProviderAndLogger = fastify({
130
162
  loggerInstance: customLogger
131
163
  }).withTypeProvider<TestTypeProvider>()
132
- type ServerWithTypeProviderAndLogger = FastifyInstance<Server, IncomingMessage, ServerResponse, typeof customLogger, TestTypeProvider>
133
- const testPluginWithTypeProviderAndLogger: FastifyPluginCallback<TestOptions, RawServerDefault, TestTypeProvider, typeof customLogger> = function (instance, opts, done) { }
134
- const testPluginWithTypeProviderAndLoggerAsync: FastifyPluginAsync<TestOptions, RawServerDefault, TestTypeProvider, typeof customLogger> = async function (instance, opts) { }
135
- const testPluginWithTypeProviderAndLoggerWithType = (instance: ServerWithTypeProviderAndLogger, opts: FastifyPluginOptions, done: (error?: FastifyError) => void) => { }
136
- const testPluginWithTypeProviderAndLoggerWithTypeAsync = async (instance: ServerWithTypeProviderAndLogger, opts: FastifyPluginOptions) => { }
164
+ type ServerWithTypeProviderAndLogger = FastifyInstance<
165
+ Server,
166
+ IncomingMessage,
167
+ ServerResponse,
168
+ typeof customLogger,
169
+ TestTypeProvider
170
+ >
171
+ const testPluginWithTypeProviderAndLogger: FastifyPluginCallback<
172
+ TestOptions,
173
+ RawServerDefault,
174
+ TestTypeProvider,
175
+ typeof customLogger
176
+ > = function (instance, opts, done) { }
177
+ const testPluginWithTypeProviderAndLoggerAsync: FastifyPluginAsync<
178
+ TestOptions,
179
+ RawServerDefault,
180
+ TestTypeProvider,
181
+ typeof customLogger
182
+ > = async function (instance, opts) { }
183
+ const testPluginWithTypeProviderAndLoggerWithType = (
184
+ instance: ServerWithTypeProviderAndLogger,
185
+ opts: FastifyPluginOptions,
186
+ done: (error?: FastifyError) => void
187
+ ) => { }
188
+ const testPluginWithTypeProviderAndLoggerWithTypeAsync = async (
189
+ instance: ServerWithTypeProviderAndLogger,
190
+ opts: FastifyPluginOptions
191
+ ) => { }
137
192
  expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginCallback))
138
193
  expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginAsync))
139
194
  expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginOpts))
140
195
  expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginOptsAsync))
141
196
  expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginOptsWithType))
142
197
  expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginOptsWithTypeAsync))
143
- // @ts-expect-error
144
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLogger))
145
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLogger, testOptions))
146
- // @ts-expect-error
147
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerAsync))
148
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerAsync, testOptions))
149
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerWithType))
150
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerWithTypeAsync))
151
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register((instance) => {
152
- expectAssignable<FastifyInstance>(instance)
153
- }))
154
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register((instance: ServerWithTypeProviderAndLogger) => {
155
- expectAssignable<ServerWithTypeProviderAndLogger>(instance)
156
- }))
157
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(async (instance) => {
158
- expectAssignable<FastifyInstance>(instance)
159
- }))
160
- expectAssignable<ServerWithTypeProviderAndLogger>(serverWithTypeProviderAndLogger.register(async (instance: ServerWithTypeProviderAndLogger) => {
161
- expectAssignable<ServerWithTypeProviderAndLogger>(instance)
162
- }))
198
+ expectAssignable<ServerWithTypeProviderAndLogger>(
199
+ // @ts-expect-error
200
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLogger)
201
+ )
202
+ expectAssignable<ServerWithTypeProviderAndLogger>(
203
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLogger, testOptions)
204
+ )
205
+ expectAssignable<ServerWithTypeProviderAndLogger>(
206
+ // @ts-expect-error
207
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerAsync)
208
+ )
209
+ expectAssignable<ServerWithTypeProviderAndLogger>(
210
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerAsync, testOptions)
211
+ )
212
+ expectAssignable<ServerWithTypeProviderAndLogger>(
213
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerWithType)
214
+ )
215
+ expectAssignable<ServerWithTypeProviderAndLogger>(
216
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerWithTypeAsync)
217
+ )
218
+ expectAssignable<ServerWithTypeProviderAndLogger>(
219
+ serverWithTypeProviderAndLogger.register((instance) => {
220
+ expectAssignable<FastifyInstance>(instance)
221
+ })
222
+ )
223
+ expectAssignable<ServerWithTypeProviderAndLogger>(
224
+ serverWithTypeProviderAndLogger.register((instance: ServerWithTypeProviderAndLogger) => {
225
+ expectAssignable<ServerWithTypeProviderAndLogger>(instance)
226
+ })
227
+ )
228
+ expectAssignable<ServerWithTypeProviderAndLogger>(
229
+ serverWithTypeProviderAndLogger.register(async (instance) => {
230
+ expectAssignable<FastifyInstance>(instance)
231
+ })
232
+ )
233
+ expectAssignable<ServerWithTypeProviderAndLogger>(
234
+ serverWithTypeProviderAndLogger.register(async (instance: ServerWithTypeProviderAndLogger) => {
235
+ expectAssignable<ServerWithTypeProviderAndLogger>(instance)
236
+ })
237
+ )
@@ -20,7 +20,9 @@ const getHandler: RouteHandlerMethod = function (_request, reply) {
20
20
  expectType<number>(reply.elapsedTime)
21
21
  expectType<number>(reply.statusCode)
22
22
  expectType<boolean>(reply.sent)
23
- expectType<(hints: Record<string, string | string[]>, callback?: (() => void) | undefined) => void>(reply.writeEarlyHints)
23
+ expectType<
24
+ (hints: Record<string, string | string[]>, callback?: (() => void) | undefined) => void
25
+ >(reply.writeEarlyHints)
24
26
  expectType<((payload?: unknown) => FastifyReply)>(reply.send)
25
27
  expectAssignable<(key: string, value: any) => FastifyReply>(reply.header)
26
28
  expectAssignable<(values: { [key: string]: any }) => FastifyReply>(reply.headers)
@@ -35,14 +37,29 @@ const getHandler: RouteHandlerMethod = function (_request, reply) {
35
37
  expectType<(fn: (payload: any) => string) => FastifyReply>(reply.serializer)
36
38
  expectType<(payload: any) => string | ArrayBuffer | Buffer>(reply.serialize)
37
39
  expectType<(fulfilled: () => void, rejected: (err: Error) => void) => void>(reply.then)
38
- expectType<(key: string, fn: ((reply: FastifyReply, payload: string | Buffer | null) => Promise<string>) | ((reply: FastifyReply, payload: string | Buffer | null, done: (err: Error | null, value?: string) => void) => void)) => FastifyReply>(reply.trailer)
40
+ expectType<
41
+ (
42
+ key: string,
43
+ fn: ((reply: FastifyReply, payload: string | Buffer | null) => Promise<string>) |
44
+ ((reply: FastifyReply, payload: string | Buffer | null,
45
+ done: (err: Error | null, value?: string) => void) => void)
46
+ ) => FastifyReply
47
+ >(reply.trailer)
39
48
  expectType<(key: string) => boolean>(reply.hasTrailer)
40
49
  expectType<(key: string) => FastifyReply>(reply.removeTrailer)
41
50
  expectType<FastifyInstance>(reply.server)
42
- expectAssignable<((httpStatus: string) => DefaultSerializationFunction | undefined)>(reply.getSerializationFunction)
43
- expectAssignable<((schema: { [key: string]: unknown }) => DefaultSerializationFunction | undefined)>(reply.getSerializationFunction)
44
- expectAssignable<((schema: { [key: string]: unknown }, httpStatus?: string) => DefaultSerializationFunction)>(reply.compileSerializationSchema)
45
- expectAssignable<((input: { [key: string]: unknown }, schema: { [key: string]: unknown }, httpStatus?: string) => unknown)>(reply.serializeInput)
51
+ expectAssignable<
52
+ ((httpStatus: string) => DefaultSerializationFunction | undefined)
53
+ >(reply.getSerializationFunction)
54
+ expectAssignable<
55
+ ((schema: { [key: string]: unknown }) => DefaultSerializationFunction | undefined)
56
+ >(reply.getSerializationFunction)
57
+ expectAssignable<
58
+ ((schema: { [key: string]: unknown }, httpStatus?: string) => DefaultSerializationFunction)
59
+ >(reply.compileSerializationSchema)
60
+ expectAssignable<
61
+ ((input: { [key: string]: unknown }, schema: { [key: string]: unknown }, httpStatus?: string) => unknown)
62
+ >(reply.serializeInput)
46
63
  expectAssignable<((input: { [key: string]: unknown }, httpStatus: string) => unknown)>(reply.serializeInput)
47
64
  expectType<ContextConfigDefault & FastifyRouteConfig & FastifyContextConfig>(reply.routeOptions.config)
48
65
  expectType<string>(reply.getDecorator<string>('foo'))
@@ -91,7 +91,9 @@ const getHandler: RouteHandler = function (request, _reply) {
91
91
  expectType<FastifyInstance>(request.server)
92
92
  expectAssignable<(httpPart: HTTPRequestPart) => ExpectedGetValidationFunction>(request.getValidationFunction)
93
93
  expectAssignable<(schema: { [key: string]: unknown }) => ExpectedGetValidationFunction>(request.getValidationFunction)
94
- expectAssignable<(input: { [key: string]: unknown }, schema: { [key: string]: unknown }, httpPart?: HTTPRequestPart) => boolean>(request.validateInput)
94
+ expectAssignable<
95
+ (input: { [key: string]: unknown }, schema: { [key: string]: unknown }, httpPart?: HTTPRequestPart) => boolean
96
+ >(request.validateInput)
95
97
  expectAssignable<(input: { [key: string]: unknown }, httpPart?: HTTPRequestPart) => boolean>(request.validateInput)
96
98
  expectType<string>(request.getDecorator<string>('foo'))
97
99
  expectType<void>(request.setDecorator('foo', 'hello'))
@@ -99,14 +101,25 @@ const getHandler: RouteHandler = function (request, _reply) {
99
101
  expectError(request.setDecorator<string>('foo', true))
100
102
  }
101
103
 
102
- const getHandlerWithCustomLogger: RouteHandlerMethod<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, CustomLoggerInterface> = function (request, _reply) {
104
+ const getHandlerWithCustomLogger: RouteHandlerMethod<
105
+ RawServerDefault,
106
+ RawRequestDefaultExpression,
107
+ RawReplyDefaultExpression,
108
+ RouteGenericInterface,
109
+ ContextConfigDefault,
110
+ FastifySchema,
111
+ FastifyTypeProviderDefault,
112
+ CustomLoggerInterface
113
+ > = function (request, _reply) {
103
114
  expectType<CustomLoggerInterface>(request.log)
104
115
  }
105
116
 
106
117
  const postHandler: Handler = function (request) {
107
118
  expectType<RequestBody>(request.body)
108
119
  expectType<RequestParams>(request.params)
109
- expectType<RequestHeaders & RawRequestDefaultExpression['headers']>(request.headers)
120
+ expectType<RequestHeaders & RawRequestDefaultExpression['headers']>(
121
+ request.headers
122
+ )
110
123
  expectType<RequestQuerystring>(request.query)
111
124
  expectType<string>(request.body.content)
112
125
  expectType<string>(request.query.from)
@@ -154,15 +167,21 @@ const customLogger: CustomLoggerInterface = {
154
167
  const serverWithCustomLogger = fastify({ loggerInstance: customLogger })
155
168
  expectError<
156
169
  FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>
157
- & Promise<FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>>
170
+ & Promise<
171
+ FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>
172
+ >
158
173
  >(serverWithCustomLogger)
159
174
  expectAssignable<
160
175
  FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>
161
- & PromiseLike<FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>>
176
+ & PromiseLike<
177
+ FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>
178
+ >
162
179
  >(serverWithCustomLogger)
163
180
  expectType<
164
181
  FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>
165
- & SafePromiseLike<FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>>
182
+ & SafePromiseLike<
183
+ FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, CustomLoggerInterface>
184
+ >
166
185
  >(serverWithCustomLogger)
167
186
 
168
187
  serverWithCustomLogger.get('/get', getHandlerWithCustomLogger)
@@ -23,7 +23,16 @@ declare module '../../fastify' {
23
23
  }
24
24
 
25
25
  /* eslint-disable @typescript-eslint/no-unused-vars */
26
- interface FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, Logger, RequestType> {
26
+ interface FastifyRequest<
27
+ RouteGeneric,
28
+ RawServer,
29
+ RawRequest,
30
+ SchemaCompiler,
31
+ TypeProvider,
32
+ ContextConfig,
33
+ Logger,
34
+ RequestType
35
+ > {
27
36
  message: ContextConfig extends { includeMessage: true }
28
37
  ? string
29
38
  : null;
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('node:test')
3
+ const { describe, test } = require('node:test')
4
4
  const Joi = require('joi')
5
5
  const Fastify = require('..')
6
6
 
@@ -831,3 +831,70 @@ test('plugin override', async (t) => {
831
831
  })
832
832
  t.assert.strictEqual(response5.statusCode, 400)
833
833
  })
834
+
835
+ describe('sync and async must work in the same way', () => {
836
+ // Route with custom validator that throws
837
+ const throwingRouteValidator = {
838
+ schema: {
839
+ body: {
840
+ type: 'object',
841
+ properties: { name: { type: 'string' } }
842
+ }
843
+ },
844
+ validatorCompiler: () => {
845
+ return function (inputData) {
846
+ // This custom validator throws a sync error instead of returning `{ error }`
847
+ throw new Error('Custom validation failed')
848
+ }
849
+ },
850
+ handler (request, reply) { reply.send({ success: true }) }
851
+ }
852
+
853
+ test('async preValidation with custom validator should trigger error handler when validator throws', async (t) => {
854
+ t.plan(4)
855
+
856
+ const fastify = Fastify()
857
+ fastify.setErrorHandler((error, request, reply) => {
858
+ t.assert.ok(error instanceof Error, 'error should be an Error instance')
859
+ t.assert.strictEqual(error.message, 'Custom validation failed')
860
+ reply.status(500).send({ error: error.message })
861
+ })
862
+
863
+ // Add async preValidation hook
864
+ fastify.addHook('preValidation', async (request, reply) => {
865
+ await Promise.resolve('ok')
866
+ })
867
+ fastify.post('/async', throwingRouteValidator)
868
+
869
+ const response = await fastify.inject({
870
+ method: 'POST',
871
+ url: '/async',
872
+ payload: { name: 'test' }
873
+ })
874
+ t.assert.strictEqual(response.statusCode, 500)
875
+ t.assert.deepStrictEqual(response.json(), { error: 'Custom validation failed' })
876
+ })
877
+
878
+ test('sync preValidation with custom validator should trigger error handler when validator throws', async (t) => {
879
+ t.plan(4)
880
+
881
+ const fastify = Fastify()
882
+ fastify.setErrorHandler((error, request, reply) => {
883
+ t.assert.ok(error instanceof Error, 'error should be an Error instance')
884
+ t.assert.strictEqual(error.message, 'Custom validation failed')
885
+ reply.status(500).send({ error: error.message })
886
+ })
887
+
888
+ // Add sync preValidation hook
889
+ fastify.addHook('preValidation', (request, reply, next) => { next() })
890
+ fastify.post('/sync', throwingRouteValidator)
891
+
892
+ const response = await fastify.inject({
893
+ method: 'POST',
894
+ url: '/sync',
895
+ payload: { name: 'test' }
896
+ })
897
+ t.assert.strictEqual(response.statusCode, 500)
898
+ t.assert.deepStrictEqual(response.json(), { error: 'Custom validation failed' })
899
+ })
900
+ })
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { test } = require('node:test')
4
4
  const { kReplyHijacked } = require('../lib/symbols')
5
- const wrapThenable = require('../lib/wrapThenable')
5
+ const wrapThenable = require('../lib/wrap-thenable')
6
6
  const Reply = require('../lib/reply')
7
7
 
8
8
  test('should resolve immediately when reply[kReplyHijacked] is true', async t => {
@@ -464,12 +464,12 @@ export interface FastifyInstance<
464
464
  /**
465
465
  * Fastify default error handler
466
466
  */
467
- errorHandler: (error: FastifyError, request: FastifyRequest, reply: FastifyReply) => void;
467
+ errorHandler: <TError = unknown>(error: TError, request: FastifyRequest, reply: FastifyReply) => void;
468
468
 
469
469
  /**
470
470
  * Set a function that will be invoked whenever an exception is thrown during the request lifecycle.
471
471
  */
472
- setErrorHandler<TError extends Error = FastifyError, RouteGeneric extends RouteGenericInterface = RouteGenericInterface, SchemaCompiler extends FastifySchema = FastifySchema, TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault>(
472
+ setErrorHandler<TError = unknown, RouteGeneric extends RouteGenericInterface = RouteGenericInterface, SchemaCompiler extends FastifySchema = FastifySchema, TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault>(
473
473
  handler: (this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>, error: TError, request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>, reply: FastifyReply<RouteGeneric, RawServer, RawRequest, RawReply, ContextConfigDefault, SchemaCompiler, TypeProvider>) => any | Promise<any>
474
474
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
475
475