fastify 4.0.0-alpha.2 → 4.0.0-alpha.3

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.
@@ -68,6 +68,7 @@ test('reply.send will logStream error and destroy the stream', t => {
68
68
  hasHeader: () => false,
69
69
  getHeader: () => undefined,
70
70
  writeHead: () => {},
71
+ write: () => {},
71
72
  headersSent: true
72
73
  })
73
74
 
@@ -89,6 +90,7 @@ test('reply.send throw with circular JSON', t => {
89
90
  hasHeader: () => false,
90
91
  getHeader: () => undefined,
91
92
  writeHead: () => {},
93
+ write: () => {},
92
94
  end: () => {}
93
95
  }
94
96
  const reply = new Reply(response, { context: { onSend: [] } })
@@ -106,6 +108,7 @@ test('reply.send returns itself', t => {
106
108
  hasHeader: () => false,
107
109
  getHeader: () => undefined,
108
110
  writeHead: () => {},
111
+ write: () => {},
109
112
  end: () => {}
110
113
  }
111
114
  const reply = new Reply(response, { context: { onSend: [] } })
@@ -264,7 +267,7 @@ test('within an instance', t => {
264
267
 
265
268
  fastify.listen({ port: 0 }, err => {
266
269
  t.error(err)
267
- fastify.server.unref()
270
+ t.teardown(fastify.close.bind(fastify))
268
271
 
269
272
  test('custom serializer should be used', t => {
270
273
  t.plan(3)
@@ -424,7 +427,7 @@ test('buffer without content type should send a application/octet-stream and raw
424
427
 
425
428
  fastify.listen({ port: 0 }, err => {
426
429
  t.error(err)
427
- fastify.server.unref()
430
+ t.teardown(fastify.close.bind(fastify))
428
431
 
429
432
  sget({
430
433
  method: 'GET',
@@ -449,7 +452,7 @@ test('buffer with content type should not send application/octet-stream', t => {
449
452
 
450
453
  fastify.listen({ port: 0 }, err => {
451
454
  t.error(err)
452
- fastify.server.unref()
455
+ t.teardown(fastify.close.bind(fastify))
453
456
 
454
457
  sget({
455
458
  method: 'GET',
@@ -477,7 +480,7 @@ test('stream with content type should not send application/octet-stream', t => {
477
480
 
478
481
  fastify.listen({ port: 0 }, err => {
479
482
  t.error(err)
480
- fastify.server.unref()
483
+ t.teardown(fastify.close.bind(fastify))
481
484
  sget({
482
485
  method: 'GET',
483
486
  url: 'http://localhost:' + fastify.server.address().port
@@ -503,7 +506,7 @@ test('stream without content type should not send application/octet-stream', t =
503
506
 
504
507
  fastify.listen({ port: 0 }, err => {
505
508
  t.error(err)
506
- fastify.server.unref()
509
+ t.teardown(fastify.close.bind(fastify))
507
510
  sget({
508
511
  method: 'GET',
509
512
  url: 'http://localhost:' + fastify.server.address().port
@@ -538,7 +541,7 @@ test('stream using reply.raw.writeHead should return customize headers', t => {
538
541
 
539
542
  fastify.listen({ port: 0 }, err => {
540
543
  t.error(err)
541
- fastify.server.unref()
544
+ t.teardown(fastify.close.bind(fastify))
542
545
  sget({
543
546
  method: 'GET',
544
547
  url: 'http://localhost:' + fastify.server.address().port
@@ -562,7 +565,7 @@ test('plain string without content type should send a text/plain', t => {
562
565
 
563
566
  fastify.listen({ port: 0 }, err => {
564
567
  t.error(err)
565
- fastify.server.unref()
568
+ t.teardown(fastify.close.bind(fastify))
566
569
 
567
570
  sget({
568
571
  method: 'GET',
@@ -586,7 +589,7 @@ test('plain string with content type should be sent unmodified', t => {
586
589
 
587
590
  fastify.listen({ port: 0 }, err => {
588
591
  t.error(err)
589
- fastify.server.unref()
592
+ t.teardown(fastify.close.bind(fastify))
590
593
 
591
594
  sget({
592
595
  method: 'GET',
@@ -613,7 +616,7 @@ test('plain string with content type and custom serializer should be serialized'
613
616
 
614
617
  fastify.listen({ port: 0 }, err => {
615
618
  t.error(err)
616
- fastify.server.unref()
619
+ t.teardown(fastify.close.bind(fastify))
617
620
 
618
621
  sget({
619
622
  method: 'GET',
@@ -637,7 +640,7 @@ test('plain string with content type application/json should NOT be serialized a
637
640
 
638
641
  fastify.listen({ port: 0 }, err => {
639
642
  t.error(err)
640
- fastify.server.unref()
643
+ t.teardown(fastify.close.bind(fastify))
641
644
 
642
645
  sget({
643
646
  method: 'GET',
@@ -690,7 +693,7 @@ test('plain string with custom json content type should NOT be serialized as jso
690
693
 
691
694
  fastify.listen({ port: 0 }, err => {
692
695
  t.error(err)
693
- fastify.server.unref()
696
+ t.teardown(fastify.close.bind(fastify))
694
697
 
695
698
  Object.keys(customSamples).forEach((path) => {
696
699
  sget({
@@ -716,7 +719,7 @@ test('non-string with content type application/json SHOULD be serialized as json
716
719
 
717
720
  fastify.listen({ port: 0 }, err => {
718
721
  t.error(err)
719
- fastify.server.unref()
722
+ t.teardown(fastify.close.bind(fastify))
720
723
 
721
724
  sget({
722
725
  method: 'GET',
@@ -729,6 +732,30 @@ test('non-string with content type application/json SHOULD be serialized as json
729
732
  })
730
733
  })
731
734
 
735
+ test('non-string with custom json\'s content-type SHOULD be serialized as json', t => {
736
+ t.plan(4)
737
+
738
+ const fastify = require('../..')()
739
+
740
+ fastify.get('/', function (req, reply) {
741
+ reply.type('application/json; version=2; ').send({ key: 'hello world!' })
742
+ })
743
+
744
+ fastify.listen({ port: 0 }, err => {
745
+ t.error(err)
746
+ t.teardown(fastify.close.bind(fastify))
747
+
748
+ sget({
749
+ method: 'GET',
750
+ url: 'http://localhost:' + fastify.server.address().port
751
+ }, (err, response, body) => {
752
+ t.error(err)
753
+ t.equal(response.headers['content-type'], 'application/json; version=2; charset=utf-8')
754
+ t.same(body.toString(), JSON.stringify({ key: 'hello world!' }))
755
+ })
756
+ })
757
+ })
758
+
732
759
  test('non-string with custom json content type SHOULD be serialized as json', t => {
733
760
  t.plan(16)
734
761
 
@@ -765,7 +792,7 @@ test('non-string with custom json content type SHOULD be serialized as json', t
765
792
 
766
793
  fastify.listen({ port: 0 }, err => {
767
794
  t.error(err)
768
- fastify.server.unref()
795
+ t.teardown(fastify.close.bind(fastify))
769
796
 
770
797
  Object.keys(customSamples).forEach((path) => {
771
798
  sget({
@@ -830,7 +857,7 @@ test('undefined payload should be sent as-is', t => {
830
857
 
831
858
  fastify.listen({ port: 0 }, err => {
832
859
  t.error(err)
833
- fastify.server.unref()
860
+ t.teardown(fastify.close.bind(fastify))
834
861
 
835
862
  sget({
836
863
  method: 'GET',
@@ -875,7 +902,7 @@ test('for HEAD method, no body should be sent but content-length should be', t =
875
902
 
876
903
  fastify.listen({ port: 0 }, err => {
877
904
  t.error(err)
878
- fastify.server.unref()
905
+ t.teardown(fastify.close.bind(fastify))
879
906
 
880
907
  sget({
881
908
  method: 'HEAD',
@@ -923,7 +950,7 @@ test('reply.send(new NotFound()) should not invoke the 404 handler', t => {
923
950
  fastify.listen({ port: 0 }, err => {
924
951
  t.error(err)
925
952
 
926
- fastify.server.unref()
953
+ t.teardown(fastify.close.bind(fastify))
927
954
 
928
955
  sget({
929
956
  method: 'GET',
@@ -969,7 +996,7 @@ test('reply can set multiple instances of same header', t => {
969
996
 
970
997
  fastify.listen({ port: 0 }, err => {
971
998
  t.error(err)
972
- fastify.server.unref()
999
+ t.teardown(fastify.close.bind(fastify))
973
1000
 
974
1001
  sget({
975
1002
  method: 'GET',
@@ -996,7 +1023,7 @@ test('reply.hasHeader returns correct values', t => {
996
1023
 
997
1024
  fastify.listen({ port: 0 }, err => {
998
1025
  t.error(err)
999
- fastify.server.unref()
1026
+ t.teardown(fastify.close.bind(fastify))
1000
1027
  sget({
1001
1028
  method: 'GET',
1002
1029
  url: 'http://localhost:' + fastify.server.address().port + '/headers'
@@ -1025,7 +1052,7 @@ test('reply.getHeader returns correct values', t => {
1025
1052
 
1026
1053
  fastify.listen({ port: 0 }, err => {
1027
1054
  t.error(err)
1028
- fastify.server.unref()
1055
+ t.teardown(fastify.close.bind(fastify))
1029
1056
  sget({
1030
1057
  method: 'GET',
1031
1058
  url: 'http://localhost:' + fastify.server.address().port + '/headers'
@@ -1095,7 +1122,7 @@ test('reply.removeHeader can remove the value', t => {
1095
1122
 
1096
1123
  fastify.listen({ port: 0 }, err => {
1097
1124
  t.error(err)
1098
- fastify.server.unref()
1125
+ t.teardown(fastify.close.bind(fastify))
1099
1126
  sget({
1100
1127
  method: 'GET',
1101
1128
  url: 'http://localhost:' + fastify.server.address().port + '/headers'
@@ -1122,7 +1149,7 @@ test('reply.header can reset the value', t => {
1122
1149
 
1123
1150
  fastify.listen({ port: 0 }, err => {
1124
1151
  t.error(err)
1125
- fastify.server.unref()
1152
+ t.teardown(fastify.close.bind(fastify))
1126
1153
  sget({
1127
1154
  method: 'GET',
1128
1155
  url: 'http://localhost:' + fastify.server.address().port + '/headers'
@@ -1151,7 +1178,7 @@ test('reply.hasHeader computes raw and fastify headers', t => {
1151
1178
 
1152
1179
  fastify.listen({ port: 0 }, err => {
1153
1180
  t.error(err)
1154
- fastify.server.unref()
1181
+ t.teardown(fastify.close.bind(fastify))
1155
1182
  sget({
1156
1183
  method: 'GET',
1157
1184
  url: 'http://localhost:' + fastify.server.address().port + '/headers'
@@ -1320,7 +1347,7 @@ test('reply.header setting multiple cookies as multiple Set-Cookie headers', t =
1320
1347
 
1321
1348
  fastify.listen({ port: 0 }, err => {
1322
1349
  t.error(err)
1323
- fastify.server.unref()
1350
+ t.teardown(fastify.close.bind(fastify))
1324
1351
 
1325
1352
  sget({
1326
1353
  method: 'GET',
@@ -35,6 +35,33 @@ test('listen works without arguments', async t => {
35
35
  t.ok(address.port > 0)
36
36
  })
37
37
 
38
+ test('Async/await listen with arguments', async t => {
39
+ process.on('warning', () => {
40
+ t.fail('should not be deprecated')
41
+ })
42
+
43
+ t.plan(1)
44
+ const fastify = Fastify()
45
+ t.teardown(fastify.close.bind(fastify))
46
+ const addr = await fastify.listen({ port: 0, host: '0.0.0.0' })
47
+ const address = fastify.server.address()
48
+ t.equal(addr, `http://${address.address}:${address.port}`)
49
+ })
50
+
51
+ test('Promise listen with arguments', t => {
52
+ process.on('warning', () => {
53
+ t.fail('should not be deprecated')
54
+ })
55
+
56
+ t.plan(1)
57
+ const fastify = Fastify()
58
+ t.teardown(fastify.close.bind(fastify))
59
+ fastify.listen({ port: 0, host: '0.0.0.0' }).then(addr => {
60
+ const address = fastify.server.address()
61
+ t.equal(addr, `http://${address.address}:${address.port}`)
62
+ })
63
+ })
64
+
38
65
  test('listen accepts a callback', t => {
39
66
  process.on('warning', () => {
40
67
  t.fail('should not be deprecated')
@@ -0,0 +1,270 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const test = t.test
5
+ const Fastify = require('..')
6
+ const { Readable } = require('stream')
7
+ const { createHash } = require('crypto')
8
+
9
+ test('send trailers when payload is empty string', t => {
10
+ t.plan(4)
11
+
12
+ const fastify = Fastify()
13
+
14
+ fastify.get('/', function (request, reply) {
15
+ reply.trailer('ETag', function (reply, payload) {
16
+ return 'custom-etag'
17
+ })
18
+ reply.send('')
19
+ })
20
+
21
+ fastify.inject({
22
+ method: 'GET',
23
+ url: '/'
24
+ }, (error, res) => {
25
+ t.error(error)
26
+ t.equal(res.statusCode, 200)
27
+ t.equal(res.headers.trailer, 'etag')
28
+ t.equal(res.trailers.etag, 'custom-etag')
29
+ })
30
+ })
31
+
32
+ test('send trailers when payload is empty buffer', t => {
33
+ t.plan(4)
34
+
35
+ const fastify = Fastify()
36
+
37
+ fastify.get('/', function (request, reply) {
38
+ reply.trailer('ETag', function (reply, payload) {
39
+ return 'custom-etag'
40
+ })
41
+ reply.send(Buffer.alloc(0))
42
+ })
43
+
44
+ fastify.inject({
45
+ method: 'GET',
46
+ url: '/'
47
+ }, (error, res) => {
48
+ t.error(error)
49
+ t.equal(res.statusCode, 200)
50
+ t.equal(res.headers.trailer, 'etag')
51
+ t.equal(res.trailers.etag, 'custom-etag')
52
+ })
53
+ })
54
+
55
+ test('send trailers when payload is undefined', t => {
56
+ t.plan(4)
57
+
58
+ const fastify = Fastify()
59
+
60
+ fastify.get('/', function (request, reply) {
61
+ reply.trailer('ETag', function (reply, payload) {
62
+ return 'custom-etag'
63
+ })
64
+ reply.send(undefined)
65
+ })
66
+
67
+ fastify.inject({
68
+ method: 'GET',
69
+ url: '/'
70
+ }, (error, res) => {
71
+ t.error(error)
72
+ t.equal(res.statusCode, 200)
73
+ t.equal(res.headers.trailer, 'etag')
74
+ t.equal(res.trailers.etag, 'custom-etag')
75
+ })
76
+ })
77
+
78
+ test('send trailers when payload is json', t => {
79
+ t.plan(6)
80
+
81
+ const fastify = Fastify()
82
+ const data = JSON.stringify({ hello: 'world' })
83
+ const hash = createHash('md5')
84
+ hash.update(data)
85
+ const md5 = hash.digest('hex')
86
+
87
+ fastify.get('/', function (request, reply) {
88
+ reply.trailer('Content-MD5', function (reply, payload) {
89
+ t.equal(data, payload)
90
+ const hash = createHash('md5')
91
+ hash.update(payload)
92
+ return hash.digest('hex')
93
+ })
94
+ reply.send(data)
95
+ })
96
+
97
+ fastify.inject({
98
+ method: 'GET',
99
+ url: '/'
100
+ }, (error, res) => {
101
+ t.error(error)
102
+ t.equal(res.statusCode, 200)
103
+ t.equal(res.headers['transfer-encoding'], 'chunked')
104
+ t.equal(res.headers.trailer, 'content-md5')
105
+ t.equal(res.trailers['content-md5'], md5)
106
+ })
107
+ })
108
+
109
+ test('send trailers when payload is stream', t => {
110
+ t.plan(6)
111
+
112
+ const fastify = Fastify()
113
+
114
+ fastify.get('/', function (request, reply) {
115
+ reply.trailer('ETag', function (reply, payload) {
116
+ t.same(payload, null)
117
+ return 'custom-etag'
118
+ })
119
+ const stream = Readable.from([JSON.stringify({ hello: 'world' })])
120
+ reply.send(stream)
121
+ })
122
+
123
+ fastify.inject({
124
+ method: 'GET',
125
+ url: '/'
126
+ }, (error, res) => {
127
+ t.error(error)
128
+ t.equal(res.statusCode, 200)
129
+ t.equal(res.headers['transfer-encoding'], 'chunked')
130
+ t.equal(res.headers.trailer, 'etag')
131
+ t.equal(res.trailers.etag, 'custom-etag')
132
+ })
133
+ })
134
+
135
+ test('removeTrailer', t => {
136
+ t.plan(5)
137
+
138
+ const fastify = Fastify()
139
+
140
+ fastify.get('/', function (request, reply) {
141
+ reply.removeTrailer('ETag') // remove nothing
142
+ reply.trailer('ETag', function (reply, payload) {
143
+ return 'custom-etag'
144
+ })
145
+ reply.trailer('Should-Not-Call', function (reply, payload) {
146
+ t.fail('it should not called as this trailer is removed')
147
+ return 'should-not-call'
148
+ })
149
+ reply.removeTrailer('Should-Not-Call')
150
+ reply.send(undefined)
151
+ })
152
+
153
+ fastify.inject({
154
+ method: 'GET',
155
+ url: '/'
156
+ }, (error, res) => {
157
+ t.error(error)
158
+ t.equal(res.statusCode, 200)
159
+ t.equal(res.headers.trailer, 'etag')
160
+ t.equal(res.trailers.etag, 'custom-etag')
161
+ t.notOk(res.trailers['should-not-call'])
162
+ })
163
+ })
164
+
165
+ test('hasTrailer', t => {
166
+ t.plan(9)
167
+
168
+ const fastify = Fastify()
169
+
170
+ fastify.get('/', function (request, reply) {
171
+ t.equal(reply.hasTrailer('ETag'), false)
172
+ reply.trailer('ETag', function (reply, payload) {
173
+ return 'custom-etag'
174
+ })
175
+ t.equal(reply.hasTrailer('ETag'), true)
176
+ reply.trailer('Should-Not-Call', function (reply, payload) {
177
+ t.fail('it should not called as this trailer is removed')
178
+ return 'should-not-call'
179
+ })
180
+ t.equal(reply.hasTrailer('Should-Not-Call'), true)
181
+ reply.removeTrailer('Should-Not-Call')
182
+ t.equal(reply.hasTrailer('Should-Not-Call'), false)
183
+ reply.send(undefined)
184
+ })
185
+
186
+ fastify.inject({
187
+ method: 'GET',
188
+ url: '/'
189
+ }, (error, res) => {
190
+ t.error(error)
191
+ t.equal(res.statusCode, 200)
192
+ t.equal(res.headers.trailer, 'etag')
193
+ t.equal(res.trailers.etag, 'custom-etag')
194
+ t.notOk(res.trailers['should-not-call'])
195
+ })
196
+ })
197
+
198
+ test('throw error when trailer header name is not allowed', t => {
199
+ const INVALID_TRAILERS = [
200
+ 'transfer-encoding',
201
+ 'content-length',
202
+ 'host',
203
+ 'cache-control',
204
+ 'max-forwards',
205
+ 'te',
206
+ 'authorization',
207
+ 'set-cookie',
208
+ 'content-encoding',
209
+ 'content-type',
210
+ 'content-range',
211
+ 'trailer'
212
+ ]
213
+ t.plan(INVALID_TRAILERS.length + 2)
214
+
215
+ const fastify = Fastify()
216
+
217
+ fastify.get('/', function (request, reply) {
218
+ for (const key of INVALID_TRAILERS) {
219
+ try {
220
+ reply.trailer(key, () => {})
221
+ } catch (err) {
222
+ t.equal(err.message, `Called reply.trailer with an invalid header name: ${key}`)
223
+ }
224
+ }
225
+ reply.send('')
226
+ })
227
+
228
+ fastify.inject({
229
+ method: 'GET',
230
+ url: '/'
231
+ }, (error, res) => {
232
+ t.error(error)
233
+ t.equal(res.statusCode, 200)
234
+ })
235
+ })
236
+
237
+ test('throw error when trailer header value is not function', t => {
238
+ const INVALID_TRAILERS_VALUE = [
239
+ undefined,
240
+ null,
241
+ true,
242
+ false,
243
+ 'invalid',
244
+ [],
245
+ new Date(),
246
+ {}
247
+ ]
248
+ t.plan(INVALID_TRAILERS_VALUE.length + 2)
249
+
250
+ const fastify = Fastify()
251
+
252
+ fastify.get('/', function (request, reply) {
253
+ for (const value of INVALID_TRAILERS_VALUE) {
254
+ try {
255
+ reply.trailer('invalid', value)
256
+ } catch (err) {
257
+ t.equal(err.message, `Called reply.trailer('invalid', fn) with an invalid type: ${typeof value}. Expected a function.`)
258
+ }
259
+ }
260
+ reply.send('')
261
+ })
262
+
263
+ fastify.inject({
264
+ method: 'GET',
265
+ url: '/'
266
+ }, (error, res) => {
267
+ t.error(error)
268
+ t.equal(res.statusCode, 200)
269
+ })
270
+ })
@@ -6,12 +6,16 @@ import fastify, {
6
6
  FastifyRequest,
7
7
  RawReplyDefaultExpression,
8
8
  RawRequestDefaultExpression,
9
- RawServerBase,
10
9
  RouteOptions,
11
10
  RegisterOptions,
12
- FastifyPluginOptions
11
+ FastifyPluginOptions,
12
+ FastifySchema,
13
+ FastifyTypeProviderDefault,
14
+ ContextConfigDefault, FastifyContextConfig, RawServerDefault
13
15
  } from '../../fastify'
14
16
  import { preHandlerAsyncHookHandler, RequestPayload } from '../../types/hooks'
17
+ import { RouteGenericInterface } from '../../types/route'
18
+ import { ResolveFastifyRequestType } from '../../types/type-provider'
15
19
 
16
20
  const server = fastify()
17
21
 
@@ -213,11 +217,15 @@ server.addHook('onClose', async (instance) => {
213
217
  // Use case to monitor any regression on issue #3620
214
218
  // ref.: https://github.com/fastify/fastify/issues/3620
215
219
  const customTypedHook: preHandlerAsyncHookHandler<
216
- RawServerBase,
220
+ RawServerDefault,
217
221
  RawRequestDefaultExpression,
218
222
  RawReplyDefaultExpression,
219
- Record<string, unknown>
220
- > = async function (request, reply) {
223
+ RouteGenericInterface,
224
+ ContextConfigDefault,
225
+ FastifySchema,
226
+ FastifyTypeProviderDefault,
227
+ ResolveFastifyRequestType<FastifyTypeProviderDefault, FastifySchema, RouteGenericInterface>
228
+ > = async function (request, reply): Promise<void> {
221
229
  expectType<FastifyInstance>(this)
222
230
  expectAssignable<FastifyRequest>(request)
223
231
  expectAssignable<FastifyReply>(reply)
@@ -226,3 +234,51 @@ Record<string, unknown>
226
234
  server.register(async (instance) => {
227
235
  instance.addHook('preHandler', customTypedHook)
228
236
  })
237
+
238
+ // Test custom Context Config types for hooks
239
+ type CustomContextConfig = FastifyContextConfig & {
240
+ foo: string;
241
+ bar: number;
242
+ }
243
+
244
+ server.route<RouteGenericInterface, CustomContextConfig>({
245
+ method: 'GET',
246
+ url: '/',
247
+ handler: () => {},
248
+ onRequest: (request, reply) => {
249
+ expectType<CustomContextConfig>(request.context.config)
250
+ expectType<CustomContextConfig>(reply.context.config)
251
+ },
252
+ preParsing: (request, reply) => {
253
+ expectType<CustomContextConfig>(request.context.config)
254
+ expectType<CustomContextConfig>(reply.context.config)
255
+ },
256
+ preValidation: (request, reply) => {
257
+ expectType<CustomContextConfig>(request.context.config)
258
+ expectType<CustomContextConfig>(reply.context.config)
259
+ },
260
+ preHandler: (request, reply) => {
261
+ expectType<CustomContextConfig>(request.context.config)
262
+ expectType<CustomContextConfig>(reply.context.config)
263
+ },
264
+ preSerialization: (request, reply) => {
265
+ expectType<CustomContextConfig>(request.context.config)
266
+ expectType<CustomContextConfig>(reply.context.config)
267
+ },
268
+ onSend: (request, reply) => {
269
+ expectType<CustomContextConfig>(request.context.config)
270
+ expectType<CustomContextConfig>(reply.context.config)
271
+ },
272
+ onResponse: (request, reply) => {
273
+ expectType<CustomContextConfig>(request.context.config)
274
+ expectType<CustomContextConfig>(reply.context.config)
275
+ },
276
+ onTimeout: (request, reply) => {
277
+ expectType<CustomContextConfig>(request.context.config)
278
+ expectType<CustomContextConfig>(reply.context.config)
279
+ },
280
+ onError: (request, reply) => {
281
+ expectType<CustomContextConfig>(request.context.config)
282
+ expectType<CustomContextConfig>(reply.context.config)
283
+ }
284
+ })