fastify 4.19.1 → 4.19.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.
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '4.19.1'
3
+ const VERSION = '4.19.2'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('http')
@@ -426,12 +426,6 @@ function fastify (options) {
426
426
  router.closeRoutes()
427
427
 
428
428
  hookRunnerApplication('preClose', fastify[kAvvioBoot], fastify, function () {
429
- // No new TCP connections are accepted.
430
- // We must call close on the server even if we are not listening
431
- // otherwise memory will be leaked.
432
- // https://github.com/nodejs/node/issues/48604
433
- instance.server.close(done)
434
-
435
429
  if (fastify[kState].listening) {
436
430
  /* istanbul ignore next: Cannot test this without Node.js core support */
437
431
  if (forceCloseConnections === 'idle') {
@@ -450,8 +444,22 @@ function fastify (options) {
450
444
  fastify[kKeepAliveConnections].delete(conn)
451
445
  }
452
446
  }
447
+ }
448
+
449
+ // No new TCP connections are accepted.
450
+ // We must call close on the server even if we are not listening
451
+ // otherwise memory will be leaked.
452
+ // https://github.com/nodejs/node/issues/48604
453
+ if (!options.serverFactory || fastify[kState].listening) {
454
+ instance.server.close(function (err) {
455
+ if (err && err.code !== 'ERR_SERVER_NOT_RUNNING') {
456
+ done(null)
457
+ } else {
458
+ done()
459
+ }
460
+ })
453
461
  } else {
454
- done(null)
462
+ process.nextTick(done, null)
455
463
  }
456
464
  })
457
465
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "4.19.1",
3
+ "version": "4.19.2",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -82,3 +82,45 @@ test('Should accept user defined serverFactory and ignore secondary server creat
82
82
  await app.listen({ port: 0 })
83
83
  })
84
84
  })
85
+
86
+ test('Should not call close on the server if it has not created it', async t => {
87
+ const server = http.createServer()
88
+
89
+ const serverFactory = (handler, opts) => {
90
+ server.on('request', handler)
91
+ return server
92
+ }
93
+
94
+ const fastify = Fastify({ serverFactory })
95
+
96
+ fastify.get('/', (req, reply) => {
97
+ reply.send({ hello: 'world' })
98
+ })
99
+
100
+ await fastify.ready()
101
+
102
+ await new Promise((resolve, reject) => {
103
+ server.listen(0)
104
+ server.on('listening', resolve)
105
+ server.on('error', reject)
106
+ })
107
+
108
+ const address = server.address()
109
+ t.equal(server.listening, true)
110
+ await fastify.close()
111
+
112
+ t.equal(server.listening, true)
113
+ t.same(server.address(), address)
114
+ t.same(fastify.addresses(), [address])
115
+
116
+ await new Promise((resolve, reject) => {
117
+ server.close((err) => {
118
+ if (err) {
119
+ return reject(err)
120
+ }
121
+ resolve()
122
+ })
123
+ })
124
+ t.equal(server.listening, false)
125
+ t.same(server.address(), null)
126
+ })
@@ -1,21 +1,21 @@
1
1
  import { FastifyError } from '@fastify/error'
2
2
  import { expectAssignable, expectError, expectType } from 'tsd'
3
3
  import fastify, {
4
+ ContextConfigDefault, FastifyContextConfig,
4
5
  FastifyInstance,
6
+ FastifyPluginOptions,
5
7
  FastifyReply,
6
8
  FastifyRequest,
9
+ FastifySchema,
10
+ FastifyTypeProviderDefault,
7
11
  RawReplyDefaultExpression,
8
12
  RawRequestDefaultExpression,
9
- RouteOptions,
13
+ RawServerDefault,
10
14
  RegisterOptions,
11
- FastifyPluginOptions,
12
- FastifySchema,
13
- FastifyTypeProviderDefault,
14
- ContextConfigDefault, FastifyContextConfig, RawServerDefault
15
+ RouteOptions
15
16
  } from '../../fastify'
16
- import { preHandlerAsyncHookHandler, RequestPayload } from '../../types/hooks'
17
- import { RouteGenericInterface } from '../../types/route'
18
- import { ResolveFastifyRequestType } from '../../types/type-provider'
17
+ import { RequestPayload, preHandlerAsyncHookHandler } from '../../types/hooks'
18
+ import { FastifyRouteConfig, RouteGenericInterface } from '../../types/route'
19
19
 
20
20
  const server = fastify()
21
21
 
@@ -252,89 +252,90 @@ type CustomContextConfig = FastifyContextConfig & {
252
252
  foo: string;
253
253
  bar: number;
254
254
  }
255
+ type CustomContextConfigWithDefault = CustomContextConfig & FastifyRouteConfig
255
256
 
256
257
  server.route<RouteGenericInterface, CustomContextConfig>({
257
258
  method: 'GET',
258
259
  url: '/',
259
260
  handler: () => { },
260
261
  onRequest: (request, reply, done) => {
261
- expectType<CustomContextConfig>(request.context.config)
262
- expectType<CustomContextConfig>(reply.context.config)
262
+ expectType<CustomContextConfigWithDefault>(request.context.config)
263
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
263
264
  },
264
265
  preParsing: (request, reply, payload, done) => {
265
- expectType<CustomContextConfig>(request.context.config)
266
- expectType<CustomContextConfig>(reply.context.config)
266
+ expectType<CustomContextConfigWithDefault>(request.context.config)
267
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
267
268
  },
268
269
  preValidation: (request, reply, done) => {
269
- expectType<CustomContextConfig>(request.context.config)
270
- expectType<CustomContextConfig>(reply.context.config)
270
+ expectType<CustomContextConfigWithDefault>(request.context.config)
271
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
271
272
  },
272
273
  preHandler: (request, reply, done) => {
273
- expectType<CustomContextConfig>(request.context.config)
274
- expectType<CustomContextConfig>(reply.context.config)
274
+ expectType<CustomContextConfigWithDefault>(request.context.config)
275
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
275
276
  },
276
277
  preSerialization: (request, reply, payload, done) => {
277
- expectType<CustomContextConfig>(request.context.config)
278
- expectType<CustomContextConfig>(reply.context.config)
278
+ expectType<CustomContextConfigWithDefault>(request.context.config)
279
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
279
280
  },
280
281
  onSend: (request, reply, payload, done) => {
281
- expectType<CustomContextConfig>(request.context.config)
282
- expectType<CustomContextConfig>(reply.context.config)
282
+ expectType<CustomContextConfigWithDefault>(request.context.config)
283
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
283
284
  },
284
285
  onResponse: (request, reply, done) => {
285
- expectType<CustomContextConfig>(request.context.config)
286
- expectType<CustomContextConfig>(reply.context.config)
286
+ expectType<CustomContextConfigWithDefault>(request.context.config)
287
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
287
288
  },
288
289
  onTimeout: (request, reply, done) => {
289
- expectType<CustomContextConfig>(request.context.config)
290
- expectType<CustomContextConfig>(reply.context.config)
290
+ expectType<CustomContextConfigWithDefault>(request.context.config)
291
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
291
292
  },
292
293
  onError: (request, reply, error, done) => {
293
- expectType<CustomContextConfig>(request.context.config)
294
- expectType<CustomContextConfig>(reply.context.config)
294
+ expectType<CustomContextConfigWithDefault>(request.context.config)
295
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
295
296
  }
296
297
  })
297
298
 
298
299
  server.get<RouteGenericInterface, CustomContextConfig>('/', {
299
300
  onRequest: async (request, reply) => {
300
- expectType<CustomContextConfig>(request.context.config)
301
- expectType<CustomContextConfig>(reply.context.config)
301
+ expectType<CustomContextConfigWithDefault>(request.context.config)
302
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
302
303
  },
303
304
  preParsing: async (request, reply) => {
304
- expectType<CustomContextConfig>(request.context.config)
305
- expectType<CustomContextConfig>(reply.context.config)
305
+ expectType<CustomContextConfigWithDefault>(request.context.config)
306
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
306
307
  },
307
308
  preValidation: async (request, reply) => {
308
- expectType<CustomContextConfig>(request.context.config)
309
- expectType<CustomContextConfig>(reply.context.config)
309
+ expectType<CustomContextConfigWithDefault>(request.context.config)
310
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
310
311
  },
311
312
  preHandler: async (request, reply) => {
312
- expectType<CustomContextConfig>(request.context.config)
313
- expectType<CustomContextConfig>(reply.context.config)
313
+ expectType<CustomContextConfigWithDefault>(request.context.config)
314
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
314
315
  },
315
316
  preSerialization: async (request, reply) => {
316
- expectType<CustomContextConfig>(request.context.config)
317
- expectType<CustomContextConfig>(reply.context.config)
317
+ expectType<CustomContextConfigWithDefault>(request.context.config)
318
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
318
319
  },
319
320
  onSend: async (request, reply) => {
320
- expectType<CustomContextConfig>(request.context.config)
321
- expectType<CustomContextConfig>(reply.context.config)
321
+ expectType<CustomContextConfigWithDefault>(request.context.config)
322
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
322
323
  },
323
324
  onResponse: async (request, reply) => {
324
- expectType<CustomContextConfig>(request.context.config)
325
- expectType<CustomContextConfig>(reply.context.config)
325
+ expectType<CustomContextConfigWithDefault>(request.context.config)
326
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
326
327
  },
327
328
  onTimeout: async (request, reply) => {
328
- expectType<CustomContextConfig>(request.context.config)
329
- expectType<CustomContextConfig>(reply.context.config)
329
+ expectType<CustomContextConfigWithDefault>(request.context.config)
330
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
330
331
  },
331
332
  onError: async (request, reply) => {
332
- expectType<CustomContextConfig>(request.context.config)
333
- expectType<CustomContextConfig>(reply.context.config)
333
+ expectType<CustomContextConfigWithDefault>(request.context.config)
334
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
334
335
  }
335
336
  }, async (request, reply) => {
336
- expectType<CustomContextConfig>(request.context.config)
337
- expectType<CustomContextConfig>(reply.context.config)
337
+ expectType<CustomContextConfigWithDefault>(request.context.config)
338
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
338
339
  })
339
340
 
340
341
  type CustomContextRequest = FastifyRequest<any, any, any, any, any, CustomContextConfig, any>
@@ -344,40 +345,40 @@ server.route<RouteGenericInterface, CustomContextConfig>({
344
345
  url: '/',
345
346
  handler: () => { },
346
347
  onRequest: async (request: CustomContextRequest, reply: CustomContextReply) => {
347
- expectType<CustomContextConfig>(request.context.config)
348
- expectType<CustomContextConfig>(reply.context.config)
348
+ expectType<CustomContextConfigWithDefault>(request.context.config)
349
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
349
350
  },
350
351
  preParsing: async (request: CustomContextRequest, reply: CustomContextReply, payload: RequestPayload) => {
351
- expectType<CustomContextConfig>(request.context.config)
352
- expectType<CustomContextConfig>(reply.context.config)
352
+ expectType<CustomContextConfigWithDefault>(request.context.config)
353
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
353
354
  },
354
355
  preValidation: async (request: CustomContextRequest, reply: CustomContextReply) => {
355
- expectType<CustomContextConfig>(request.context.config)
356
- expectType<CustomContextConfig>(reply.context.config)
356
+ expectType<CustomContextConfigWithDefault>(request.context.config)
357
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
357
358
  },
358
359
  preHandler: async (request: CustomContextRequest, reply: CustomContextReply) => {
359
- expectType<CustomContextConfig>(request.context.config)
360
- expectType<CustomContextConfig>(reply.context.config)
360
+ expectType<CustomContextConfigWithDefault>(request.context.config)
361
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
361
362
  },
362
363
  preSerialization: async (request: CustomContextRequest, reply: CustomContextReply, payload: any) => {
363
- expectType<CustomContextConfig>(request.context.config)
364
- expectType<CustomContextConfig>(reply.context.config)
364
+ expectType<CustomContextConfigWithDefault>(request.context.config)
365
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
365
366
  },
366
367
  onSend: async (request: CustomContextRequest, reply: CustomContextReply, payload: any) => {
367
- expectType<CustomContextConfig>(request.context.config)
368
- expectType<CustomContextConfig>(reply.context.config)
368
+ expectType<CustomContextConfigWithDefault>(request.context.config)
369
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
369
370
  },
370
371
  onResponse: async (request: CustomContextRequest, reply: CustomContextReply) => {
371
- expectType<CustomContextConfig>(request.context.config)
372
- expectType<CustomContextConfig>(reply.context.config)
372
+ expectType<CustomContextConfigWithDefault>(request.context.config)
373
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
373
374
  },
374
375
  onTimeout: async (request: CustomContextRequest, reply: CustomContextReply) => {
375
- expectType<CustomContextConfig>(request.context.config)
376
- expectType<CustomContextConfig>(reply.context.config)
376
+ expectType<CustomContextConfigWithDefault>(request.context.config)
377
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
377
378
  },
378
379
  onError: async (request: CustomContextRequest, reply: CustomContextReply, error: FastifyError) => {
379
- expectType<CustomContextConfig>(request.context.config)
380
- expectType<CustomContextConfig>(reply.context.config)
380
+ expectType<CustomContextConfigWithDefault>(request.context.config)
381
+ expectType<CustomContextConfigWithDefault>(reply.context.config)
381
382
  }
382
383
  })
383
384
 
@@ -315,6 +315,8 @@ server.decorate<string>('test', {
315
315
  expectType<FastifyInstance>(this)
316
316
  }
317
317
  })
318
+ server.decorate('test')
319
+ server.decorate('test', null, ['foo'])
318
320
 
319
321
  server.decorateRequest<(x: string, y: number) => void>('test', function (x: string, y: number): void {
320
322
  expectType<FastifyRequest>(this)
@@ -322,6 +324,8 @@ server.decorateRequest<(x: string, y: number) => void>('test', function (x: stri
322
324
  server.decorateRequest('test', function (x: string, y: number): void {
323
325
  expectType<FastifyRequest>(this)
324
326
  })
327
+ server.decorateRequest('test')
328
+ server.decorateRequest('test', null, ['foo'])
325
329
 
326
330
  server.decorateReply<(x: string) => void>('test', function (x: string): void {
327
331
  expectType<FastifyReply>(this)
@@ -329,6 +333,8 @@ server.decorateReply<(x: string) => void>('test', function (x: string): void {
329
333
  server.decorateReply('test', function (x: string): void {
330
334
  expectType<FastifyReply>(this)
331
335
  })
336
+ server.decorateReply('test')
337
+ server.decorateReply('test', null, ['foo'])
332
338
 
333
339
  expectError(server.decorate<string>('test', true))
334
340
  expectError(server.decorate<(myNumber: number) => number>('test', function (myNumber: number): string {
@@ -349,7 +355,20 @@ declare module '../../fastify' {
349
355
  typedTestPropertyGetterSetter: string
350
356
  typedTestMethod (x: string): string
351
357
  }
358
+
359
+ interface FastifyRequest {
360
+ typedTestRequestProperty: boolean
361
+ typedTestRequestPropertyGetterSetter: string
362
+ typedTestRequestMethod (x: string): string
363
+ }
364
+
365
+ interface FastifyReply {
366
+ typedTestReplyProperty: boolean
367
+ typedTestReplyPropertyGetterSetter: string
368
+ typedTestReplyMethod (x: string): string
369
+ }
352
370
  }
371
+
353
372
  server.decorate('typedTestProperty', false)
354
373
  server.decorate('typedTestProperty', {
355
374
  getter () {
@@ -365,6 +384,9 @@ server.decorate('typedTestProperty', {
365
384
  expectType<FastifyInstance>(this)
366
385
  }
367
386
  })
387
+ server.decorate('typedTestProperty')
388
+ server.decorate('typedTestProperty', null, ['foo'])
389
+ server.decorate('typedTestProperty', null)
368
390
  expectError(server.decorate('typedTestProperty', 'foo'))
369
391
  expectError(server.decorate('typedTestProperty', {
370
392
  getter () {
@@ -387,6 +409,86 @@ expectError(server.decorate('typedTestMethod', async function (x) {
387
409
  return 'foo'
388
410
  }))
389
411
 
412
+ server.decorateRequest('typedTestRequestProperty', false)
413
+ server.decorateRequest('typedTestRequestProperty', {
414
+ getter () {
415
+ return false
416
+ }
417
+ })
418
+ server.decorateRequest('typedTestRequestProperty', {
419
+ getter (): boolean {
420
+ return true
421
+ },
422
+ setter (x) {
423
+ expectType<boolean>(x)
424
+ expectType<FastifyRequest>(this)
425
+ }
426
+ })
427
+ server.decorateRequest('typedTestRequestProperty')
428
+ server.decorateRequest('typedTestRequestProperty', null, ['foo'])
429
+ server.decorateRequest('typedTestRequestProperty', null)
430
+ expectError(server.decorateRequest('typedTestRequestProperty', 'foo'))
431
+ expectError(server.decorateRequest('typedTestRequestProperty', {
432
+ getter () {
433
+ return 'foo'
434
+ }
435
+ }))
436
+ server.decorateRequest('typedTestRequestMethod', function (x) {
437
+ expectType<string>(x)
438
+ expectType<FastifyRequest>(this)
439
+ return 'foo'
440
+ })
441
+ server.decorateRequest('typedTestRequestMethod', x => x)
442
+ expectError(server.decorateRequest('typedTestRequestMethod', function (x: boolean) {
443
+ return 'foo'
444
+ }))
445
+ expectError(server.decorateRequest('typedTestRequestMethod', function (x) {
446
+ return true
447
+ }))
448
+ expectError(server.decorateRequest('typedTestRequestMethod', async function (x) {
449
+ return 'foo'
450
+ }))
451
+
452
+ server.decorateReply('typedTestReplyProperty', false)
453
+ server.decorateReply('typedTestReplyProperty', {
454
+ getter () {
455
+ return false
456
+ }
457
+ })
458
+ server.decorateReply('typedTestReplyProperty', {
459
+ getter (): boolean {
460
+ return true
461
+ },
462
+ setter (x) {
463
+ expectType<boolean>(x)
464
+ expectType<FastifyReply>(this)
465
+ }
466
+ })
467
+ server.decorateReply('typedTestReplyProperty')
468
+ server.decorateReply('typedTestReplyProperty', null, ['foo'])
469
+ server.decorateReply('typedTestReplyProperty', null)
470
+ expectError(server.decorateReply('typedTestReplyProperty', 'foo'))
471
+ expectError(server.decorateReply('typedTestReplyProperty', {
472
+ getter () {
473
+ return 'foo'
474
+ }
475
+ }))
476
+ server.decorateReply('typedTestReplyMethod', function (x) {
477
+ expectType<string>(x)
478
+ expectType<FastifyReply>(this)
479
+ return 'foo'
480
+ })
481
+ server.decorateReply('typedTestReplyMethod', x => x)
482
+ expectError(server.decorateReply('typedTestReplyMethod', function (x: boolean) {
483
+ return 'foo'
484
+ }))
485
+ expectError(server.decorateReply('typedTestReplyMethod', function (x) {
486
+ return true
487
+ }))
488
+ expectError(server.decorateReply('typedTestReplyMethod', async function (x) {
489
+ return 'foo'
490
+ }))
491
+
390
492
  const versionConstraintStrategy = {
391
493
  name: 'version',
392
494
  storage: () => ({
@@ -1,19 +1,19 @@
1
- import { expectType, expectError, expectAssignable } from 'tsd'
2
- import fastify, { RouteHandlerMethod, RouteHandler, RawRequestDefaultExpression, FastifyContext, FastifyContextConfig, FastifyRequest, FastifyReply, FastifySchema, FastifyTypeProviderDefault } from '../../fastify'
3
- import { RawServerDefault, RawReplyDefaultExpression, ContextConfigDefault } from '../../types/utils'
1
+ import { Buffer } from 'buffer'
2
+ import { expectAssignable, expectError, expectType } from 'tsd'
3
+ import fastify, { FastifyContext, FastifyReply, FastifyRequest, FastifySchema, FastifySchemaCompiler, FastifyTypeProviderDefault, RawRequestDefaultExpression, RouteHandler, RouteHandlerMethod } from '../../fastify'
4
+ import { FastifyInstance } from '../../types/instance'
4
5
  import { FastifyLoggerInstance } from '../../types/logger'
6
+ import { ResolveReplyTypeWithRouteGeneric } from '../../types/reply'
5
7
  import { RouteGenericInterface } from '../../types/route'
6
- import { FastifyInstance } from '../../types/instance'
7
- import { Buffer } from 'buffer'
8
- import { ReplyTypeConstrainer } from '../../types/reply'
8
+ import { ContextConfigDefault, RawReplyDefaultExpression, RawServerDefault } from '../../types/utils'
9
9
 
10
10
  type DefaultSerializationFunction = (payload: { [key: string]: unknown }) => string
11
- type DefaultFastifyReplyWithCode<Code extends number> = FastifyReply<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, ReplyTypeConstrainer<RouteGenericInterface['Reply'], Code>>
11
+ type DefaultFastifyReplyWithCode<Code extends number> = FastifyReply<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, ResolveReplyTypeWithRouteGeneric<RouteGenericInterface['Reply'], Code, FastifySchema, FastifyTypeProviderDefault>>
12
12
 
13
13
  const getHandler: RouteHandlerMethod = function (_request, reply) {
14
14
  expectType<RawReplyDefaultExpression>(reply.raw)
15
15
  expectType<FastifyContext<ContextConfigDefault>>(reply.context)
16
- expectType<FastifyContextConfig>(reply.context.config)
16
+ expectType<FastifyContext<ContextConfigDefault>['config']>(reply.context.config)
17
17
  expectType<FastifyLoggerInstance>(reply.log)
18
18
  expectType<FastifyRequest<RouteGenericInterface, RawServerDefault, RawRequestDefaultExpression>>(reply.request)
19
19
  expectType<<Code extends number>(statusCode: Code) => DefaultFastifyReplyWithCode<Code>>(reply.code)
@@ -1,26 +1,25 @@
1
- import { expectAssignable, expectType } from 'tsd'
2
1
  import pino from 'pino'
2
+ import { expectAssignable, expectType } from 'tsd'
3
3
  import fastify, {
4
- RouteHandler,
5
- RawRequestDefaultExpression,
6
- RequestBodyDefault,
7
- RequestGenericInterface,
8
- FastifyContext,
9
4
  ContextConfigDefault,
10
- FastifyContextConfig,
5
+ FastifyContext,
11
6
  FastifyLogFn,
12
- RouteHandlerMethod,
13
- RawServerDefault,
14
- RawReplyDefaultExpression,
15
7
  FastifySchema,
16
- FastifyTypeProviderDefault
8
+ FastifyTypeProviderDefault,
9
+ RawReplyDefaultExpression,
10
+ RawRequestDefaultExpression,
11
+ RawServerDefault,
12
+ RequestBodyDefault,
13
+ RequestGenericInterface,
14
+ RouteHandler,
15
+ RouteHandlerMethod
17
16
  } from '../../fastify'
18
- import { RequestParamsDefault, RequestHeadersDefault, RequestQuerystringDefault } from '../../types/utils'
17
+ import { FastifyInstance } from '../../types/instance'
19
18
  import { FastifyLoggerInstance } from '../../types/logger'
20
- import { FastifyRequest, RequestRouteOptions } from '../../types/request'
21
19
  import { FastifyReply } from '../../types/reply'
22
- import { FastifyInstance } from '../../types/instance'
20
+ import { FastifyRequest, RequestRouteOptions } from '../../types/request'
23
21
  import { RouteGenericInterface } from '../../types/route'
22
+ import { RequestHeadersDefault, RequestParamsDefault, RequestQuerystringDefault } from '../../types/utils'
24
23
 
25
24
  interface RequestBody {
26
25
  content: string;
@@ -76,8 +75,8 @@ const getHandler: RouteHandler = function (request, _reply) {
76
75
  expectType<RequestBodyDefault>(request.body)
77
76
  expectType<RequestParamsDefault>(request.params)
78
77
  expectType<FastifyContext<ContextConfigDefault>>(request.context)
79
- expectType<FastifyContextConfig>(request.context.config)
80
- expectType<FastifyContextConfig>(request.routeConfig)
78
+ expectType<FastifyContext<ContextConfigDefault>['config']>(request.context.config)
79
+ expectType<FastifyContext<ContextConfigDefault>['config']>(request.routeConfig)
81
80
  expectType<FastifySchema>(request.routeSchema)
82
81
 
83
82
  expectType<RequestHeadersDefault & RawRequestDefaultExpression['headers']>(request.headers)
@@ -110,7 +109,7 @@ const postHandler: Handler = function (request) {
110
109
  expectType<string>(request.headers['x-foobar'])
111
110
  expectType<FastifyInstance>(request.server)
112
111
  expectType<FastifyContext<ContextConfigDefault>>(request.context)
113
- expectType<FastifyContextConfig>(request.context.config)
112
+ expectType<FastifyContext<ContextConfigDefault>['config']>(request.context.config)
114
113
  }
115
114
 
116
115
  function putHandler (request: CustomRequest, reply: FastifyReply) {
@@ -128,7 +127,7 @@ function putHandler (request: CustomRequest, reply: FastifyReply) {
128
127
  expectType<string>(request.headers['x-foobar'])
129
128
  expectType<FastifyInstance>(request.server)
130
129
  expectType<FastifyContext<ContextConfigDefault>>(request.context)
131
- expectType<FastifyContextConfig>(request.context.config)
130
+ expectType<FastifyContext<ContextConfigDefault>['config']>(request.context.config)
132
131
  }
133
132
 
134
133
  const server = fastify()
@@ -1,9 +1,9 @@
1
- import fastify, { FastifyInstance, FastifyRequest, FastifyReply, RouteHandlerMethod } from '../../fastify'
2
- import { expectType, expectError, expectAssignable, printType } from 'tsd'
3
- import { HTTPMethods } from '../../types/utils'
1
+ import { FastifyError } from '@fastify/error'
4
2
  import * as http from 'http'
3
+ import { expectAssignable, expectError, expectType } from 'tsd'
4
+ import fastify, { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from '../../fastify'
5
5
  import { RequestPayload } from '../../types/hooks'
6
- import { FastifyError } from '@fastify/error'
6
+ import { HTTPMethods } from '../../types/utils'
7
7
 
8
8
  /*
9
9
  * Testing Fastify HTTP Routes and Route Shorthands.
@@ -74,7 +74,7 @@ type LowerCaseHTTPMethods = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'
74
74
  Headers: HeadersInterface;
75
75
  }
76
76
 
77
- fastify()[lowerCaseMethod]<RouteGeneric, RouteSpecificContextConfigType>('/', { config: { foo: 'bar', bar: 100, extra: true, url: '/', method: lowerCaseMethod } }, (req, res) => {
77
+ fastify()[lowerCaseMethod]<RouteGeneric, RouteSpecificContextConfigType>('/', { config: { foo: 'bar', bar: 100, extra: true } }, (req, res) => {
78
78
  expectType<BodyInterface>(req.body)
79
79
  expectType<QuerystringInterface>(req.query)
80
80
  expectType<ParamsInterface>(req.params)
@@ -94,7 +94,7 @@ type LowerCaseHTTPMethods = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'
94
94
  fastify().route<RouteGeneric>({
95
95
  url: '/',
96
96
  method: method as HTTPMethods,
97
- config: { foo: 'bar', bar: 100, url: '/', method: method as HTTPMethods },
97
+ config: { foo: 'bar', bar: 100 },
98
98
  prefixTrailingSlash: 'slash',
99
99
  onRequest: (req, res, done) => { // these handlers are tested in `hooks.test-d.ts`
100
100
  expectType<BodyInterface>(req.body)
@@ -231,7 +231,7 @@ type LowerCaseHTTPMethods = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'
231
231
  fastify().route<RouteGeneric>({
232
232
  url: '/',
233
233
  method: method as HTTPMethods,
234
- config: { foo: 'bar', bar: 100, url: '/', method: method as HTTPMethods },
234
+ config: { foo: 'bar', bar: 100 },
235
235
  prefixTrailingSlash: 'slash',
236
236
  onRequest: async (req, res, done) => { // these handlers are tested in `hooks.test-d.ts`
237
237
  expectType<BodyInterface>(req.body)
@@ -299,6 +299,8 @@ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
299
299
  res.send('hello')
300
300
  res.send(42)
301
301
  res.send({ error: 'error' })
302
+ expectType<(payload?: string | number | { error: string }) => typeof res>(res.code(200).send)
303
+ expectError<(payload?: unknown) => typeof res>(res.code(200).send)
302
304
  }
303
305
  ))
304
306
 
@@ -527,6 +529,8 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
527
529
  res.send('hello')
528
530
  res.send(42)
529
531
  res.send({ error: 'error' })
532
+ expectType<(payload?: string | number | { [x: string]: unknown, error?: string | undefined }) => typeof res>(res.code(200).send)
533
+ expectError<(payload?: unknown) => typeof res>(res.code(200).send)
530
534
  }
531
535
  ))
532
536
 
@@ -1,8 +1,8 @@
1
- import { ContextConfigDefault } from './utils'
2
1
  import { FastifyRouteConfig } from './route'
2
+ import { ContextConfigDefault } from './utils'
3
3
 
4
4
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
5
- export interface FastifyContextConfig extends FastifyRouteConfig {
5
+ export interface FastifyContextConfig {
6
6
  }
7
7
 
8
8
  /**
@@ -12,5 +12,5 @@ export interface FastifyContext<ContextConfig = ContextConfigDefault> {
12
12
  /**
13
13
  * @deprecated Use Request#routeConfig or Request#routeSchema instead
14
14
  */
15
- config: FastifyContextConfig & ContextConfig;
15
+ config: FastifyContextConfig & FastifyRouteConfig & ContextConfig;
16
16
  }
@@ -103,6 +103,12 @@ type DecorationMethod<This, Return = This> = {
103
103
  >,
104
104
  dependencies?: string[]
105
105
  ): Return;
106
+
107
+ (property: string | symbol): Return;
108
+
109
+ (property: string | symbol, value: null): Return;
110
+
111
+ (property: string | symbol, value: null|undefined, dependencies: string[]): Return;
106
112
  }
107
113
 
108
114
  /**
package/types/reply.d.ts CHANGED
@@ -6,17 +6,22 @@ import { FastifyRequest } from './request'
6
6
  import { RouteGenericInterface } from './route'
7
7
  import { FastifySchema } from './schema'
8
8
  import { FastifyReplyType, FastifyTypeProvider, FastifyTypeProviderDefault, ResolveFastifyReplyType } from './type-provider'
9
- import { CodeToReplyKey, ContextConfigDefault, ReplyKeysToCodes, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerBase, RawServerDefault, ReplyDefault } from './utils'
9
+ import { CodeToReplyKey, ContextConfigDefault, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerBase, RawServerDefault, ReplyDefault, ReplyKeysToCodes } from './utils'
10
10
 
11
11
  export interface ReplyGenericInterface {
12
12
  Reply?: ReplyDefault;
13
13
  }
14
14
 
15
- export type ReplyTypeConstrainer<RouteGenericReply, Code extends ReplyKeysToCodes<keyof RouteGenericReply>, ReplyKey = CodeToReplyKey<Code>> =
15
+ type ReplyTypeConstrainer<RouteGenericReply, Code extends ReplyKeysToCodes<keyof RouteGenericReply>, ReplyKey = CodeToReplyKey<Code>> =
16
16
  Code extends keyof RouteGenericReply ? RouteGenericReply[Code] :
17
17
  [ReplyKey] extends [never] ? unknown :
18
18
  ReplyKey extends keyof RouteGenericReply ? RouteGenericReply[ReplyKey] :
19
19
  unknown;
20
+
21
+ export type ResolveReplyTypeWithRouteGeneric<RouteGenericReply, Code extends ReplyKeysToCodes<keyof RouteGenericReply>,
22
+ SchemaCompiler extends FastifySchema = FastifySchema,
23
+ TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault> =
24
+ ResolveFastifyReplyType<TypeProvider, SchemaCompiler, { Reply: ReplyTypeConstrainer<RouteGenericReply, Code> }>
20
25
  /**
21
26
  * FastifyReply is an instance of the standard http or http2 reply types.
22
27
  * It defaults to http.ServerResponse, and it also extends the relative reply object.
@@ -36,8 +41,8 @@ export interface FastifyReply<
36
41
  log: FastifyBaseLogger;
37
42
  request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider>;
38
43
  server: FastifyInstance;
39
- code<Code extends ReplyKeysToCodes<keyof RouteGeneric['Reply']>>(statusCode: Code): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReplyTypeConstrainer<RouteGeneric['Reply'], Code>>;
40
- status<Code extends ReplyKeysToCodes<keyof RouteGeneric['Reply']>>(statusCode: Code): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ReplyTypeConstrainer<RouteGeneric['Reply'], Code>>;
44
+ code<Code extends ReplyKeysToCodes<keyof RouteGeneric['Reply']>>(statusCode: Code): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ResolveReplyTypeWithRouteGeneric<RouteGeneric['Reply'], Code, SchemaCompiler, TypeProvider>>;
45
+ status<Code extends ReplyKeysToCodes<keyof RouteGeneric['Reply']>>(statusCode: Code): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, ResolveReplyTypeWithRouteGeneric<RouteGeneric['Reply'], Code, SchemaCompiler, TypeProvider>>;
41
46
  statusCode: number;
42
47
  sent: boolean;
43
48
  send(payload?: ReplyType): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
@@ -1,11 +1,11 @@
1
1
  import { ErrorObject } from '@fastify/ajv-compiler'
2
+ import { FastifyContext } from './context'
3
+ import { FastifyInstance } from './instance'
2
4
  import { FastifyBaseLogger } from './logger'
3
- import { ContextConfigDefault, RawServerBase, RawServerDefault, RawRequestDefaultExpression, RequestBodyDefault, RequestQuerystringDefault, RequestParamsDefault, RequestHeadersDefault } from './utils'
4
5
  import { RouteGenericInterface } from './route'
5
- import { FastifyInstance } from './instance'
6
- import { FastifyTypeProvider, FastifyTypeProviderDefault, FastifyRequestType, ResolveFastifyRequestType } from './type-provider'
7
6
  import { FastifySchema } from './schema'
8
- import { FastifyContext, FastifyContextConfig } from './context'
7
+ import { FastifyRequestType, FastifyTypeProvider, FastifyTypeProviderDefault, ResolveFastifyRequestType } from './type-provider'
8
+ import { ContextConfigDefault, RawRequestDefaultExpression, RawServerBase, RawServerDefault, RequestBodyDefault, RequestHeadersDefault, RequestParamsDefault, RequestQuerystringDefault } from './utils'
9
9
 
10
10
  type HTTPRequestPart = 'body' | 'query' | 'querystring' | 'params' | 'headers'
11
11
  export interface RequestGenericInterface {
@@ -59,7 +59,7 @@ export interface FastifyRequest<RouteGeneric extends RouteGenericInterface = Rou
59
59
  server: FastifyInstance;
60
60
  body: RequestType['body'];
61
61
  context: FastifyContext<ContextConfig>;
62
- routeConfig: FastifyContextConfig & ContextConfig;
62
+ routeConfig: FastifyContext<ContextConfig>['config'];
63
63
  routeSchema: FastifySchema
64
64
 
65
65
  /** in order for this to be used the user should ensure they have set the attachValidation option. */
package/types/route.d.ts CHANGED
@@ -1,17 +1,17 @@
1
+ import { FastifyError } from '@fastify/error'
2
+ import { FastifyContext } from './context'
3
+ import { onErrorHookHandler, onRequestAbortHookHandler, onRequestHookHandler, onResponseHookHandler, onSendHookHandler, onTimeoutHookHandler, preHandlerHookHandler, preParsingHookHandler, preSerializationHookHandler, preValidationHookHandler } from './hooks'
1
4
  import { FastifyInstance } from './instance'
2
- import { FastifyRequest, RequestGenericInterface } from './request'
5
+ import { FastifyBaseLogger, LogLevel } from './logger'
3
6
  import { FastifyReply, ReplyGenericInterface } from './reply'
7
+ import { FastifyRequest, RequestGenericInterface } from './request'
4
8
  import { FastifySchema, FastifySchemaCompiler, FastifySerializerCompiler, SchemaErrorFormatter } from './schema'
5
- import { HTTPMethods, RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, ContextConfigDefault } from './utils'
6
- import { preValidationHookHandler, preHandlerHookHandler, preSerializationHookHandler, onRequestHookHandler, preParsingHookHandler, onResponseHookHandler, onSendHookHandler, onErrorHookHandler, onTimeoutHookHandler, onRequestAbortHookHandler } from './hooks'
7
- import { FastifyError } from '@fastify/error'
8
- import { FastifyContext } from './context'
9
9
  import {
10
10
  FastifyTypeProvider,
11
11
  FastifyTypeProviderDefault,
12
12
  ResolveFastifyReplyReturnType
13
13
  } from './type-provider'
14
- import { FastifyBaseLogger, LogLevel } from './logger'
14
+ import { ContextConfigDefault, HTTPMethods, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerBase, RawServerDefault } from './utils'
15
15
 
16
16
  export interface FastifyRouteConfig {
17
17
  url: string;
@@ -41,7 +41,7 @@ export interface RouteShorthandOptions<
41
41
  serializerCompiler?: FastifySerializerCompiler<SchemaCompiler>;
42
42
  bodyLimit?: number;
43
43
  logLevel?: LogLevel;
44
- config?: FastifyContext<ContextConfig>['config'];
44
+ config?: Omit<FastifyContext<ContextConfig>['config'], 'url' | 'method'>;
45
45
  version?: string;
46
46
  constraints?: { [name: string]: any },
47
47
  prefixTrailingSlash?: 'slash'|'no-slash'|'both';