fastify 4.21.0 → 4.22.0

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.
@@ -44,6 +44,9 @@ section.
44
44
  Fastify.
45
45
  - [`@fastify/diagnostics-channel`](https://github.com/fastify/fastify-diagnostics-channel)
46
46
  Plugin to deal with `diagnostics_channel` on Fastify
47
+ - [`@fastify/early-hints`](https://github.com/fastify/fastify-early-hints) Plugin
48
+ to add HTTP 103 feature based on [RFC
49
+ 8297](https://httpwg.org/specs/rfc8297.html).
47
50
  - [`@fastify/elasticsearch`](https://github.com/fastify/fastify-elasticsearch)
48
51
  Plugin to share the same ES client.
49
52
  - [`@fastify/env`](https://github.com/fastify/fastify-env) Load and check
@@ -304,9 +307,6 @@ section.
304
307
  object.
305
308
  - [`fastify-dynareg`](https://github.com/greguz/fastify-dynareg) Dynamic plugin
306
309
  register for Fastify.
307
- - [`fastify-early-hints`](https://github.com/zekth/fastify-early-hints) Plugin
308
- to add HTTP 103 feature based on [RFC
309
- 8297](https://httpwg.org/specs/rfc8297.html)
310
310
  - [`fastify-envalid`](https://github.com/alemagio/fastify-envalid) Fastify
311
311
  plugin to integrate [envalid](https://github.com/af/envalid) in your Fastify
312
312
  project.
@@ -358,6 +358,8 @@ section.
358
358
  Providers.
359
359
  - [`fastify-guard`](https://github.com/hsynlms/fastify-guard) A Fastify plugin
360
360
  that protects endpoints by checking authenticated user roles and/or scopes.
361
+ - [`fastify-hashids`](https://github.com/andersonjoseph/fastify-hashids) A Fastify
362
+ plugin to encode/decode IDs using [hashids](https://github.com/niieani/hashids.js).
361
363
  - [`fastify-hasura`](https://github.com/ManUtopiK/fastify-hasura) A Fastify
362
364
  plugin to have fun with [Hasura](https://github.com/hasura/graphql-engine).
363
365
  - [`fastify-healthcheck`](https://github.com/smartiniOnGitHub/fastify-healthcheck)
@@ -277,7 +277,7 @@ async function dbConnector (fastify, options) {
277
277
 
278
278
  // Wrapping a plugin function with fastify-plugin exposes the decorators
279
279
  // and hooks, declared inside the plugin to the parent scope.
280
- module.exports = fastifyPlugin(dbConnector)
280
+ export default fastifyPlugin(dbConnector)
281
281
 
282
282
  ```
283
283
 
@@ -106,6 +106,9 @@ returned stream. This property is used to correctly match the request payload
106
106
  with the `Content-Length` header value. Ideally, this property should be updated
107
107
  on each received chunk.
108
108
 
109
+ **Notice:** The size of the returned stream is checked to not exceed the limit
110
+ set in [`bodyLimit`](./Server.md#bodylimit) option.
111
+
109
112
  ### preValidation
110
113
 
111
114
  If you are using the `preValidation` hook, you can change the payload before it
@@ -282,6 +282,10 @@ attacks](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_
282
282
  + Default: `1048576` (1MiB)
283
283
 
284
284
  Defines the maximum payload, in bytes, the server is allowed to accept.
285
+ The default body reader sends [`FST_ERR_CTP_BODY_TOO_LARGE`](./Errors.md#fst_err_ctp_body_too_large)
286
+ reply, if the size of the body exceeds this limit.
287
+ If [`preParsing` hook](./Hooks.md#preparsing) is provided, this limit is applied
288
+ to the size of the stream the hook returns (i.e. the size of "decoded" body).
285
289
 
286
290
  ### `onProtoPoisoning`
287
291
  <a id="factory-on-proto-poisoning"></a>
@@ -397,7 +397,7 @@ configuration](https://github.com/fastify/ajv-compiler#ajv-configuration) is:
397
397
  {
398
398
  coerceTypes: 'array', // change data type of data to match type keyword
399
399
  useDefaults: true, // replace missing properties and items with the values from corresponding default keyword
400
- removeAdditional: true, // remove additional properties
400
+ removeAdditional: true, // remove additional properties if additionalProperties is set to false, see: https://ajv.js.org/guide/modifying-data.html#removing-additional-properties
401
401
  uriResolver: require('fast-uri'),
402
402
  addUsedSchema: false,
403
403
  // Explicitly set allErrors to `false`.
package/fastify.d.ts CHANGED
@@ -20,15 +20,15 @@ import { FastifyRegister, FastifyRegisterOptions, RegisterOptions } from './type
20
20
  import { FastifyReply } from './types/reply'
21
21
  import { FastifyRequest, RequestGenericInterface } from './types/request'
22
22
  import { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler, RouteGenericInterface } from './types/route'
23
- import { FastifySchema, FastifySchemaCompiler, SchemaErrorDataVar, SchemaErrorFormatter } from './types/schema'
23
+ import { FastifySchema, FastifySchemaCompiler, FastifySchemaValidationError, SchemaErrorDataVar, SchemaErrorFormatter } from './types/schema'
24
24
  import { FastifyServerFactory, FastifyServerFactoryHandler } from './types/serverFactory'
25
25
  import { FastifyTypeProvider, FastifyTypeProviderDefault } from './types/type-provider'
26
26
  import { HTTPMethods, RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault, ContextConfigDefault, RequestBodyDefault, RequestQuerystringDefault, RequestParamsDefault, RequestHeadersDefault } from './types/utils'
27
27
 
28
28
  declare module '@fastify/error' {
29
29
  interface FastifyError {
30
- validation?: fastify.ValidationResult[];
31
30
  validationContext?: SchemaErrorDataVar;
31
+ validation?: FastifySchemaValidationError[];
32
32
  }
33
33
  }
34
34
 
@@ -162,13 +162,10 @@ declare namespace fastify {
162
162
  clientErrorHandler?: (error: ConnectionError, socket: Socket) => void,
163
163
  }
164
164
 
165
- export interface ValidationResult {
166
- keyword: string;
167
- instancePath: string;
168
- schemaPath: string;
169
- params: Record<string, string | string[]>;
170
- message?: string;
171
- }
165
+ /**
166
+ * @deprecated use {@link FastifySchemaValidationError}
167
+ */
168
+ export type ValidationResult = FastifySchemaValidationError;
172
169
 
173
170
  /* Export additional types */
174
171
  export type {
@@ -241,4 +238,4 @@ declare function fastify<
241
238
 
242
239
  // CJS export
243
240
  // const fastify = require('fastify')
244
- export = fastify
241
+ export = fastify
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '4.21.0'
3
+ const VERSION = '4.22.0'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('http')
@@ -241,7 +241,7 @@ function fastify (options) {
241
241
  [kReply]: Reply.buildReply(Reply),
242
242
  [kRequest]: Request.buildRequest(Request, options.trustProxy),
243
243
  [kFourOhFour]: fourOhFour,
244
- [pluginUtils.registeredPlugins]: [],
244
+ [pluginUtils.kRegisteredPlugins]: [],
245
245
  [kPluginNameChain]: ['fastify'],
246
246
  [kAvvioBoot]: null,
247
247
  // routing method
@@ -312,7 +312,7 @@ function fastify (options) {
312
312
  close: null,
313
313
  printPlugins: null,
314
314
  hasPlugin: function (name) {
315
- return this[kPluginNameChain].includes(name)
315
+ return this[pluginUtils.kRegisteredPlugins].includes(name) || this[kPluginNameChain].includes(name)
316
316
  },
317
317
  // http server
318
318
  listen,
@@ -226,8 +226,11 @@ function rawBody (request, reply, options, parser, done) {
226
226
 
227
227
  function onData (chunk) {
228
228
  receivedLength += chunk.length
229
-
230
- if ((payload.receivedEncodedLength || receivedLength) > limit) {
229
+ const { receivedEncodedLength = 0 } = payload
230
+ // The resulting body length must not exceed bodyLimit (see "zip bomb").
231
+ // The case when encoded length is larger than received length is rather theoretical,
232
+ // unless the stream returned by preParsing hook is broken and reports wrong value.
233
+ if (receivedLength > limit || receivedEncodedLength > limit) {
231
234
  payload.removeListener('data', onData)
232
235
  payload.removeListener('end', onEnd)
233
236
  payload.removeListener('error', onEnd)
@@ -16,41 +16,43 @@
16
16
  ) {
17
17
 
18
18
 
19
- function anonymous0 (input) {
20
- // #
21
19
 
20
+ // #
21
+ function anonymous0 (input) {
22
22
  const obj = (input && typeof input.toJSON === 'function')
23
23
  ? input.toJSON()
24
24
  : input
25
25
 
26
- let json = '{'
27
- let addComma = false
26
+
27
+ let addComma = false
28
+ let json = '{'
29
+
30
+ if (obj["statusCode"] !== undefined) {
31
+ !addComma && (addComma = true) || (json += ',')
32
+ json += "\"statusCode\":"
33
+ json += serializer.asNumber(obj["statusCode"])
34
+ }
35
+
36
+ if (obj["code"] !== undefined) {
37
+ !addComma && (addComma = true) || (json += ',')
38
+ json += "\"code\":"
39
+ json += serializer.asString(obj["code"])
40
+ }
41
+
42
+ if (obj["error"] !== undefined) {
43
+ !addComma && (addComma = true) || (json += ',')
44
+ json += "\"error\":"
45
+ json += serializer.asString(obj["error"])
46
+ }
47
+
48
+ if (obj["message"] !== undefined) {
49
+ !addComma && (addComma = true) || (json += ',')
50
+ json += "\"message\":"
51
+ json += serializer.asString(obj["message"])
52
+ }
53
+
54
+ return json + '}'
28
55
 
29
- if (obj["statusCode"] !== undefined) {
30
- !addComma && (addComma = true) || (json += ',')
31
- json += "\"statusCode\":"
32
- json += serializer.asNumber(obj["statusCode"])
33
- }
34
-
35
- if (obj["code"] !== undefined) {
36
- !addComma && (addComma = true) || (json += ',')
37
- json += "\"code\":"
38
- json += serializer.asString(obj["code"])
39
- }
40
-
41
- if (obj["error"] !== undefined) {
42
- !addComma && (addComma = true) || (json += ',')
43
- json += "\"error\":"
44
- json += serializer.asString(obj["error"])
45
- }
46
-
47
- if (obj["message"] !== undefined) {
48
- !addComma && (addComma = true) || (json += ',')
49
- json += "\"message\":"
50
- json += serializer.asString(obj["message"])
51
- }
52
-
53
- return json + '}'
54
56
  }
55
57
 
56
58
  const main = anonymous0
@@ -27,9 +27,10 @@ const pluginUtils = require('./pluginUtils')
27
27
  module.exports = function override (old, fn, opts) {
28
28
  const shouldSkipOverride = pluginUtils.registerPlugin.call(old, fn)
29
29
 
30
+ const fnName = pluginUtils.getPluginName(fn) || pluginUtils.getFuncPreview(fn)
30
31
  if (shouldSkipOverride) {
31
32
  // after every plugin registration we will enter a new name
32
- old[kPluginNameChain].push(pluginUtils.getDisplayName(fn))
33
+ old[kPluginNameChain].push(fnName)
33
34
  return old
34
35
  }
35
36
 
@@ -48,8 +49,14 @@ module.exports = function override (old, fn, opts) {
48
49
  instance[kSchemaController] = SchemaController.buildSchemaController(old[kSchemaController])
49
50
  instance.getSchema = instance[kSchemaController].getSchema.bind(instance[kSchemaController])
50
51
  instance.getSchemas = instance[kSchemaController].getSchemas.bind(instance[kSchemaController])
51
- instance[pluginUtils.registeredPlugins] = Object.create(instance[pluginUtils.registeredPlugins])
52
- instance[kPluginNameChain] = [pluginUtils.getPluginName(fn) || pluginUtils.getFuncPreview(fn)]
52
+
53
+ // Track the registered and loaded plugins since the root instance.
54
+ // It does not track the current encapsulated plugin.
55
+ instance[pluginUtils.kRegisteredPlugins] = Object.create(instance[pluginUtils.kRegisteredPlugins])
56
+
57
+ // Track the plugin chain since the root instance.
58
+ // When an non-encapsulated plugin is added, the chain will be updated.
59
+ instance[kPluginNameChain] = [fnName]
53
60
 
54
61
  if (instance[kLogSerializers] || opts.logSerializers) {
55
62
  instance[kLogSerializers] = Object.assign(Object.create(instance[kLogSerializers]), opts.logSerializers)
@@ -2,7 +2,7 @@
2
2
 
3
3
  const semver = require('semver')
4
4
  const assert = require('assert')
5
- const registeredPlugins = Symbol.for('registered-plugin')
5
+ const kRegisteredPlugins = Symbol.for('registered-plugin')
6
6
  const {
7
7
  kTestInternals
8
8
  } = require('./symbols.js')
@@ -25,12 +25,15 @@ function getPluginName (func) {
25
25
  // let's see if this is a file, and in that case use that
26
26
  // this is common for plugins
27
27
  const cache = require.cache
28
- const keys = Object.keys(cache)
29
-
30
- for (let i = 0; i < keys.length; i++) {
31
- const key = keys[i]
32
- if (cache[key].exports === func) {
33
- return key
28
+ // cache is undefined inside SEA
29
+ if (cache) {
30
+ const keys = Object.keys(cache)
31
+
32
+ for (let i = 0; i < keys.length; i++) {
33
+ const key = keys[i]
34
+ if (cache[key].exports === func) {
35
+ return key
36
+ }
34
37
  }
35
38
  }
36
39
 
@@ -65,7 +68,7 @@ function checkDependencies (fn) {
65
68
 
66
69
  dependencies.forEach(dependency => {
67
70
  assert(
68
- this[registeredPlugins].indexOf(dependency) > -1,
71
+ this[kRegisteredPlugins].indexOf(dependency) > -1,
69
72
  `The dependency '${dependency}' of plugin '${meta.name}' is not registered`
70
73
  )
71
74
  })
@@ -128,7 +131,7 @@ function registerPluginName (fn) {
128
131
 
129
132
  const name = meta.name
130
133
  if (!name) return
131
- this[registeredPlugins].push(name)
134
+ this[kRegisteredPlugins].push(name)
132
135
  }
133
136
 
134
137
  function registerPlugin (fn) {
@@ -142,7 +145,7 @@ function registerPlugin (fn) {
142
145
  module.exports = {
143
146
  getPluginName,
144
147
  getFuncPreview,
145
- registeredPlugins,
148
+ kRegisteredPlugins,
146
149
  getDisplayName,
147
150
  registerPlugin
148
151
  }
@@ -18,7 +18,10 @@ function wrapThenable (thenable, reply) {
18
18
  // the request may be terminated during the reply. in this situation,
19
19
  // it require an extra checking of request.aborted to see whether
20
20
  // the request is killed by client.
21
- if (payload !== undefined || (reply.sent === false && reply.raw.headersSent === false && reply.request.raw.aborted === false)) {
21
+ // Most of the times aborted will be true when destroyed is true,
22
+ // however there is a race condition where the request is not
23
+ // aborted but only destroyed.
24
+ if (payload !== undefined || (reply.sent === false && reply.raw.headersSent === false && reply.request.raw.aborted === false && reply.request.raw.destroyed === false)) {
22
25
  // we use a try-catch internally to avoid adding a catch to another
23
26
  // promise, increase promise perf by 10%
24
27
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "4.21.0",
3
+ "version": "4.22.0",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -14,10 +14,11 @@
14
14
  "coverage:ci": "c8 --reporter=lcov tap --coverage-report=html --no-browser --no-check-coverage",
15
15
  "coverage:ci-check-coverage": "c8 check-coverage --branches 100 --functions 100 --lines 100 --statements 100",
16
16
  "lint": "npm run lint:standard && npm run lint:typescript && npm run lint:markdown",
17
- "lint:fix": "standard --fix",
17
+ "lint:fix": "standard --fix && npm run lint:typescript:fix",
18
18
  "lint:markdown": "markdownlint-cli2",
19
19
  "lint:standard": "standard | snazzy",
20
20
  "lint:typescript": "eslint -c types/.eslintrc.json types/**/*.d.ts test/types/**/*.test-d.ts",
21
+ "lint:typescript:fix": "npm run lint:typescript -- --fix",
21
22
  "prepublishOnly": "cross-env PREPUBLISH=true tap --no-check-coverage test/build/**.test.js && npm run test:validator:integrity",
22
23
  "test": "npm run lint && npm run unit && npm run test:typescript",
23
24
  "test:ci": "npm run unit -- --cov --coverage-report=lcovonly && npm run test:typescript",
@@ -133,11 +134,11 @@
133
134
  "homepage": "https://www.fastify.io/",
134
135
  "devDependencies": {
135
136
  "@fastify/pre-commit": "^2.0.2",
136
- "@sinclair/typebox": "^0.29.1",
137
+ "@sinclair/typebox": "^0.31.1",
137
138
  "@sinonjs/fake-timers": "^11.0.0",
138
139
  "@types/node": "^20.1.0",
139
- "@typescript-eslint/eslint-plugin": "^5.59.2",
140
- "@typescript-eslint/parser": "^5.59.2",
140
+ "@typescript-eslint/eslint-plugin": "^6.3.0",
141
+ "@typescript-eslint/parser": "^6.3.0",
141
142
  "ajv": "^8.12.0",
142
143
  "ajv-errors": "^3.0.0",
143
144
  "ajv-formats": "^2.1.1",
@@ -2,6 +2,7 @@
2
2
 
3
3
  const Fastify = require('..')
4
4
  const sget = require('simple-get').concat
5
+ const zlib = require('zlib')
5
6
  const t = require('tap')
6
7
  const test = t.test
7
8
 
@@ -45,6 +46,74 @@ test('bodyLimit', t => {
45
46
  })
46
47
  })
47
48
 
49
+ test('bodyLimit is applied to decoded content', t => {
50
+ t.plan(9)
51
+
52
+ const body = { x: 'x'.repeat(30000) }
53
+ const json = JSON.stringify(body)
54
+ const encoded = zlib.gzipSync(json)
55
+
56
+ const fastify = Fastify()
57
+
58
+ fastify.addHook('preParsing', async (req, reply, payload) => {
59
+ t.equal(req.headers['content-length'], `${encoded.length}`)
60
+ const unzip = zlib.createGunzip()
61
+ Object.defineProperty(unzip, 'receivedEncodedLength', {
62
+ get () {
63
+ return unzip.bytesWritten
64
+ }
65
+ })
66
+ payload.pipe(unzip)
67
+ return unzip
68
+ })
69
+
70
+ fastify.post('/body-limit-40k', {
71
+ bodyLimit: 40000,
72
+ onError: async (req, res, err) => {
73
+ t.fail('should not be called')
74
+ }
75
+ }, (request, reply) => {
76
+ reply.send({ x: request.body.x })
77
+ })
78
+
79
+ fastify.post('/body-limit-20k', {
80
+ bodyLimit: 20000,
81
+ onError: async (req, res, err) => {
82
+ t.equal(err.code, 'FST_ERR_CTP_BODY_TOO_LARGE')
83
+ t.equal(err.statusCode, 413)
84
+ }
85
+ }, (request, reply) => {
86
+ reply.send({ x: 'handler should not be called' })
87
+ })
88
+
89
+ fastify.inject({
90
+ method: 'POST',
91
+ url: '/body-limit-40k',
92
+ headers: {
93
+ 'content-encoding': 'gzip',
94
+ 'content-type': 'application/json'
95
+ },
96
+ payload: encoded
97
+ }, (err, res) => {
98
+ t.error(err)
99
+ t.equal(res.statusCode, 200)
100
+ t.same(res.json(), body)
101
+ })
102
+
103
+ fastify.inject({
104
+ method: 'POST',
105
+ url: '/body-limit-20k',
106
+ headers: {
107
+ 'content-encoding': 'gzip',
108
+ 'content-type': 'application/json'
109
+ },
110
+ payload: encoded
111
+ }, (err, res) => {
112
+ t.error(err)
113
+ t.equal(res.statusCode, 413)
114
+ })
115
+ })
116
+
48
117
  test('default request.routeOptions.bodyLimit should be 1048576', t => {
49
118
  t.plan(4)
50
119
  const fastify = Fastify()
@@ -10,8 +10,9 @@ const dns = require('dns').promises
10
10
 
11
11
  test('Should support a custom http server', async t => {
12
12
  const localAddresses = await dns.lookup('localhost', { all: true })
13
+ const minPlan = localAddresses.length - 1 || 1
13
14
 
14
- t.plan((localAddresses.length - 1) + 3)
15
+ t.plan(minPlan + 3)
15
16
 
16
17
  const serverFactory = (handler, opts) => {
17
18
  t.ok(opts.serverFactory, 'it is called once for localhost')
@@ -12,8 +12,9 @@ t.before(buildCertificate)
12
12
 
13
13
  test('Should support a custom https server', async t => {
14
14
  const localAddresses = await dns.lookup('localhost', { all: true })
15
+ const minPlan = localAddresses.length - 1 || 1
15
16
 
16
- t.plan((localAddresses.length - 1) + 3)
17
+ t.plan(minPlan + 3)
17
18
 
18
19
  const serverFactory = (handler, opts) => {
19
20
  t.ok(opts.serverFactory, 'it is called once for localhost')
@@ -29,6 +29,21 @@ test('getPluginName should return plugin name if the file is cached', t => {
29
29
  t.equal(pluginName, expectedPluginName)
30
30
  })
31
31
 
32
+ test('getPluginName should not throw when require.cache is undefined', t => {
33
+ t.plan(1)
34
+ function example () {
35
+ console.log('is just an example')
36
+ }
37
+ const cache = require.cache
38
+ require.cache = undefined
39
+ t.teardown(() => {
40
+ require.cache = cache
41
+ })
42
+ const pluginName = pluginUtilsPublic.getPluginName(example)
43
+
44
+ t.equal(pluginName, 'example')
45
+ })
46
+
32
47
  test("getMeta should return the object stored with the 'plugin-meta' symbol", t => {
33
48
  t.plan(1)
34
49
 
@@ -122,7 +137,7 @@ test('checkDependencies should check if the given dependency is present in the i
122
137
  }
123
138
 
124
139
  function context () {}
125
- context[pluginUtilsPublic.registeredPlugins] = ['plugin']
140
+ context[pluginUtilsPublic.kRegisteredPlugins] = ['plugin']
126
141
 
127
142
  try {
128
143
  pluginUtils.checkDependencies.call(context, fn)
@@ -143,7 +158,7 @@ test('checkDependencies should check if the given dependency is present in the i
143
158
  }
144
159
 
145
160
  function context () {}
146
- context[pluginUtilsPublic.registeredPlugins] = []
161
+ context[pluginUtilsPublic.kRegisteredPlugins] = []
147
162
 
148
163
  try {
149
164
  pluginUtils.checkDependencies.call(context, fn)
@@ -1247,3 +1247,29 @@ test('hasPlugin returns true when using no encapsulation', async t => {
1247
1247
 
1248
1248
  await fastify.ready()
1249
1249
  })
1250
+
1251
+ test('hasPlugin returns true when using encapsulation', async t => {
1252
+ t.plan(2)
1253
+
1254
+ const fastify = Fastify()
1255
+
1256
+ const pluginCallback = function (server, options, done) {
1257
+ done()
1258
+ }
1259
+ const pluginName = 'awesome-plugin'
1260
+ const plugin = fp(pluginCallback, { name: pluginName })
1261
+
1262
+ fastify.register(plugin)
1263
+
1264
+ fastify.register(async (server) => {
1265
+ t.ok(server.hasPlugin(pluginName))
1266
+ })
1267
+
1268
+ fastify.register(async function foo (server) {
1269
+ server.register(async function bar (server) {
1270
+ t.ok(server.hasPlugin(pluginName))
1271
+ })
1272
+ })
1273
+
1274
+ await fastify.ready()
1275
+ })
@@ -10,7 +10,6 @@ import fastify, {
10
10
  InjectOptions, FastifyBaseLogger,
11
11
  RawRequestDefaultExpression,
12
12
  RouteGenericInterface,
13
- ValidationResult,
14
13
  FastifyErrorCodes,
15
14
  FastifyError
16
15
  } from '../../fastify'
@@ -18,7 +17,7 @@ import { ErrorObject as AjvErrorObject } from 'ajv'
18
17
  import * as http from 'http'
19
18
  import * as https from 'https'
20
19
  import * as http2 from 'http2'
21
- import { expectType, expectError, expectAssignable } from 'tsd'
20
+ import { expectType, expectError, expectAssignable, expectNotAssignable } from 'tsd'
22
21
  import { FastifyLoggerInstance } from '../../types/logger'
23
22
  import { Socket } from 'net'
24
23
 
@@ -244,7 +243,13 @@ const ajvErrorObject: AjvErrorObject = {
244
243
  params: {},
245
244
  message: ''
246
245
  }
247
- expectAssignable<ValidationResult>(ajvErrorObject)
246
+ expectNotAssignable<AjvErrorObject>({
247
+ keyword: '',
248
+ instancePath: '',
249
+ schemaPath: '',
250
+ params: '',
251
+ message: ''
252
+ })
248
253
 
249
254
  expectAssignable<FastifyError['validation']>([ajvErrorObject])
250
255
  expectAssignable<FastifyError['validationContext']>('body')
@@ -392,3 +392,16 @@ server.addHook('preClose', function (done) {
392
392
  server.addHook('preClose', async function () {
393
393
  expectType<FastifyInstance>(this)
394
394
  })
395
+
396
+ expectError(server.addHook('onClose', async function (instance, done) {}))
397
+ expectError(server.addHook('onError', async function (request, reply, error, done) {}))
398
+ expectError(server.addHook('onReady', async function (done) {}))
399
+ expectError(server.addHook('onRequest', async function (request, reply, done) {}))
400
+ expectError(server.addHook('onRequestAbort', async function (request, done) {}))
401
+ expectError(server.addHook('onResponse', async function (request, reply, done) {}))
402
+ expectError(server.addHook('onSend', async function (request, reply, payload, done) {}))
403
+ expectError(server.addHook('onTimeout', async function (request, reply, done) {}))
404
+ expectError(server.addHook('preClose', async function (done) {}))
405
+ expectError(server.addHook('preHandler', async function (request, reply, done) {}))
406
+ expectError(server.addHook('preSerialization', async function (request, reply, payload, done) {}))
407
+ expectError(server.addHook('preValidation', async function (request, reply, done) {}))
@@ -6,7 +6,8 @@ import fastify, {
6
6
  FastifyInstance,
7
7
  RawReplyDefaultExpression,
8
8
  RawRequestDefaultExpression,
9
- RawServerDefault
9
+ RawServerDefault,
10
+ RouteGenericInterface
10
11
  } from '../../fastify'
11
12
  import { HookHandlerDoneFunction } from '../../types/hooks'
12
13
  import { FastifyReply } from '../../types/reply'
@@ -257,9 +258,13 @@ expectNotDeprecated(server.listen({ port: 3000, host: '::/0', ipv6Only: true },
257
258
 
258
259
  expectAssignable<void>(server.routing({} as RawRequestDefaultExpression, {} as RawReplyDefaultExpression))
259
260
 
260
- expectType<FastifyInstance>(fastify().get('/', {
261
+ expectType<FastifyInstance>(fastify().get<RouteGenericInterface, { contextKey: string }>('/', {
261
262
  handler: () => {},
262
263
  errorHandler: (error, request, reply) => {
264
+ expectAssignable<FastifyError>(error)
265
+ expectAssignable<FastifyRequest>(request)
266
+ expectAssignable<{ contextKey: string }>(request.routeConfig)
267
+ expectAssignable<FastifyReply>(reply)
263
268
  expectAssignable<void>(server.errorHandler(error, request, reply))
264
269
  }
265
270
  }))
@@ -83,7 +83,7 @@ const getHandler: RouteHandler = function (request, _reply) {
83
83
  request.headers = {}
84
84
 
85
85
  expectType<RequestQuerystringDefault>(request.query)
86
- expectType<any>(request.id)
86
+ expectType<string>(request.id)
87
87
  expectType<FastifyLoggerInstance>(request.log)
88
88
  expectType<RawRequestDefaultExpression['socket']>(request.socket)
89
89
  expectType<Error & { validation: any; validationContext: string } | undefined>(request.validationError)
@@ -3,7 +3,8 @@ import fastify, {
3
3
  HookHandlerDoneFunction,
4
4
  FastifyRequest,
5
5
  FastifyReply,
6
- FastifyInstance
6
+ FastifyInstance,
7
+ FastifyError
7
8
  } from '../../fastify'
8
9
  import { expectAssignable, expectError, expectType } from 'tsd'
9
10
  import { IncomingHttpHeaders } from 'http'
@@ -79,6 +80,14 @@ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
79
80
  y: Type.Number(),
80
81
  z: Type.Number()
81
82
  })
83
+ },
84
+ errorHandler: (error, request, reply) => {
85
+ expectType<FastifyError>(error)
86
+ expectAssignable<FastifyRequest>(request)
87
+ expectType<number>(request.body.x)
88
+ expectType<number>(request.body.y)
89
+ expectType<number>(request.body.z)
90
+ expectAssignable<FastifyReply>(reply)
82
91
  }
83
92
  },
84
93
  (req) => {
@@ -108,6 +117,14 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
108
117
  z: { type: 'boolean' }
109
118
  }
110
119
  } as const
120
+ },
121
+ errorHandler: (error, request, reply) => {
122
+ expectType<FastifyError>(error)
123
+ expectAssignable<FastifyRequest>(request)
124
+ expectType<number | undefined>(request.body.x)
125
+ expectType<string | undefined>(request.body.y)
126
+ expectType<boolean | undefined>(request.body.z)
127
+ expectAssignable<FastifyReply>(reply)
111
128
  }
112
129
  },
113
130
  (req) => {
@@ -135,6 +152,14 @@ expectAssignable(server.withTypeProvider<TypeBoxProvider>().withTypeProvider<Jso
135
152
  z: { type: 'boolean' }
136
153
  }
137
154
  } as const
155
+ },
156
+ errorHandler: (error, request, reply) => {
157
+ expectType<FastifyError>(error)
158
+ expectAssignable<FastifyRequest>(request)
159
+ expectType<number | undefined>(request.body.x)
160
+ expectType<string | undefined>(request.body.y)
161
+ expectType<boolean | undefined>(request.body.z)
162
+ expectAssignable<FastifyReply>(reply)
138
163
  }
139
164
  },
140
165
  (req) => {
@@ -27,3 +27,25 @@ test('should reject immediately when reply[kReplyHijacked] is true', t => {
27
27
  const thenable = Promise.reject(new Error('Reply sent already'))
28
28
  wrapThenable(thenable, reply)
29
29
  })
30
+
31
+ test('should not send the payload if the raw socket was destroyed but not aborted', async t => {
32
+ const reply = {
33
+ sent: false,
34
+ raw: {
35
+ headersSent: false
36
+ },
37
+ request: {
38
+ raw: {
39
+ aborted: false,
40
+ destroyed: true
41
+ }
42
+ },
43
+ send () {
44
+ t.fail('should not send')
45
+ }
46
+ }
47
+ const thenable = Promise.resolve()
48
+ wrapThenable(thenable, reply)
49
+
50
+ await thenable
51
+ })
package/types/hooks.d.ts CHANGED
@@ -190,7 +190,7 @@ interface DoneFuncWithErrOrRes {
190
190
  * Note: the hook is NOT called if the payload is a string, a Buffer, a stream or null.
191
191
  */
192
192
  export interface preSerializationHookHandler<
193
- PreSerializationPayload,
193
+ PreSerializationPayload = unknown,
194
194
  RawServer extends RawServerBase = RawServerDefault,
195
195
  RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
196
196
  RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
@@ -210,7 +210,7 @@ export interface preSerializationHookHandler<
210
210
  }
211
211
 
212
212
  export interface preSerializationAsyncHookHandler<
213
- PreSerializationPayload,
213
+ PreSerializationPayload = unknown,
214
214
  RawServer extends RawServerBase = RawServerDefault,
215
215
  RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
216
216
  RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
@@ -233,7 +233,7 @@ export interface preSerializationAsyncHookHandler<
233
233
  * Note: If you change the payload, you may only change it to a string, a Buffer, a stream, or null.
234
234
  */
235
235
  export interface onSendHookHandler<
236
- OnSendPayload,
236
+ OnSendPayload = unknown,
237
237
  RawServer extends RawServerBase = RawServerDefault,
238
238
  RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
239
239
  RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
@@ -253,7 +253,7 @@ export interface onSendHookHandler<
253
253
  }
254
254
 
255
255
  export interface onSendAsyncHookHandler<
256
- OnSendPayload,
256
+ OnSendPayload = unknown,
257
257
  RawServer extends RawServerBase = RawServerDefault,
258
258
  RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
259
259
  RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
@@ -432,6 +432,66 @@ export interface onRequestAbortAsyncHookHandler<
432
432
  ): Promise<unknown>;
433
433
  }
434
434
 
435
+ export type LifecycleHook = 'onRequest'
436
+ | 'preParsing'
437
+ | 'preValidation'
438
+ | 'preHandler'
439
+ | 'preSerialization'
440
+ | 'onSend'
441
+ | 'onResponse'
442
+ | 'onRequest'
443
+ | 'onError'
444
+ | 'onTimeout'
445
+ | 'onRequestAbort'
446
+
447
+ export type LifecycleHookLookup<K extends LifecycleHook> = K extends 'onRequest'
448
+ ? onRequestHookHandler
449
+ : K extends 'preParsing'
450
+ ? preParsingHookHandler
451
+ : K extends 'preValidation'
452
+ ? preValidationHookHandler
453
+ : K extends 'preHandler'
454
+ ? preHandlerHookHandler
455
+ : K extends 'preSerialization'
456
+ ? preSerializationHookHandler
457
+ : K extends 'onSend'
458
+ ? onSendHookHandler
459
+ : K extends 'onResponse'
460
+ ? onResponseHookHandler
461
+ : K extends 'onRequest'
462
+ ? onRequestHookHandler
463
+ : K extends 'onError'
464
+ ? onErrorHookHandler
465
+ : K extends 'onTimeout'
466
+ ? onTimeoutHookHandler
467
+ : K extends 'onRequestAbort'
468
+ ? onRequestAbortHookHandler
469
+ : never
470
+
471
+ export type LifecycleHookAsyncLookup<K extends LifecycleHook> = K extends 'onRequest'
472
+ ? onRequestAsyncHookHandler
473
+ : K extends 'preParsing'
474
+ ? preParsingAsyncHookHandler
475
+ : K extends 'preValidation'
476
+ ? preValidationAsyncHookHandler
477
+ : K extends 'preHandler'
478
+ ? preHandlerAsyncHookHandler
479
+ : K extends 'preSerialization'
480
+ ? preSerializationAsyncHookHandler
481
+ : K extends 'onSend'
482
+ ? onSendAsyncHookHandler
483
+ : K extends 'onResponse'
484
+ ? onResponseAsyncHookHandler
485
+ : K extends 'onRequest'
486
+ ? onRequestAsyncHookHandler
487
+ : K extends 'onError'
488
+ ? onErrorAsyncHookHandler
489
+ : K extends 'onTimeout'
490
+ ? onTimeoutAsyncHookHandler
491
+ : K extends 'onRequestAbort'
492
+ ? onRequestAbortAsyncHookHandler
493
+ : never
494
+
435
495
  // Application Hooks
436
496
 
437
497
  /**
@@ -555,3 +615,43 @@ export interface preCloseAsyncHookHandler<
555
615
  this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>,
556
616
  ): Promise<unknown>;
557
617
  }
618
+
619
+ export type ApplicationHook = 'onRoute'
620
+ | 'onRegister'
621
+ | 'onReady'
622
+ | 'onClose'
623
+ | 'preClose'
624
+
625
+ export type ApplicationHookLookup<K extends ApplicationHook> = K extends 'onRegister'
626
+ ? onRegisterHookHandler
627
+ : K extends 'onReady'
628
+ ? onReadyHookHandler
629
+ : K extends 'onClose'
630
+ ? onCloseHookHandler
631
+ : K extends 'preClose'
632
+ ? preCloseHookHandler
633
+ : K extends 'onRoute'
634
+ ? onRouteHookHandler
635
+ : never
636
+
637
+ export type ApplicationHookAsyncLookup<K extends ApplicationHook> = K extends 'onRegister'
638
+ ? onRegisterHookHandler
639
+ : K extends 'onReady'
640
+ ? onReadyAsyncHookHandler
641
+ : K extends 'onClose'
642
+ ? onCloseAsyncHookHandler
643
+ : K extends 'preClose'
644
+ ? preCloseAsyncHookHandler
645
+ : never
646
+
647
+ export type HookLookup <K extends ApplicationHook | LifecycleHook> = K extends ApplicationHook
648
+ ? ApplicationHookLookup<K>
649
+ : K extends LifecycleHook
650
+ ? LifecycleHookLookup<K>
651
+ : never
652
+
653
+ export type HookAsyncLookup <K extends ApplicationHook | LifecycleHook> = K extends ApplicationHook
654
+ ? ApplicationHookAsyncLookup<K>
655
+ : K extends LifecycleHook
656
+ ? LifecycleHookAsyncLookup<K>
657
+ : never
@@ -3,7 +3,7 @@ import { ConstraintStrategy, HTTPVersion } from 'find-my-way'
3
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
- import { onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onRequestAbortAsyncHookHandler, onRequestAbortHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, preCloseHookHandler, preCloseAsyncHookHandler } from './hooks'
6
+ import { onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onRequestAbortAsyncHookHandler, onRequestAbortHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, preCloseHookHandler, preCloseAsyncHookHandler, LifecycleHook, ApplicationHook, HookAsyncLookup, HookLookup } from './hooks'
7
7
  import { FastifyBaseLogger, FastifyChildLoggerFactory } from './logger'
8
8
  import { FastifyRegister } from './register'
9
9
  import { FastifyReply } from './reply'
@@ -30,6 +30,8 @@ export interface PrintRoutesOptions {
30
30
  includeHooks?: boolean
31
31
  }
32
32
 
33
+ type AsyncFunction = (...args: any) => Promise<any>;
34
+
33
35
  export interface FastifyListenOptions {
34
36
  /**
35
37
  * Default to `0` (picks the first available open port).
@@ -224,20 +226,11 @@ export interface FastifyInstance<
224
226
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
225
227
  ContextConfig = ContextConfigDefault,
226
228
  SchemaCompiler extends FastifySchema = FastifySchema,
227
- Logger extends FastifyBaseLogger = FastifyBaseLogger
228
- >(
229
- name: 'onRequest',
230
- hook: onRequestHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
231
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
232
-
233
- addHook<
234
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
235
- ContextConfig = ContextConfigDefault,
236
- SchemaCompiler extends FastifySchema = FastifySchema,
237
- Logger extends FastifyBaseLogger = FastifyBaseLogger
229
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
230
+ Fn extends onRequestHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | onRequestAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = onRequestHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
238
231
  >(
239
232
  name: 'onRequest',
240
- hook: onRequestAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
233
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onRequestAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : onRequestHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
241
234
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
242
235
 
243
236
  /**
@@ -248,20 +241,11 @@ export interface FastifyInstance<
248
241
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
249
242
  ContextConfig = ContextConfigDefault,
250
243
  SchemaCompiler extends FastifySchema = FastifySchema,
251
- Logger extends FastifyBaseLogger = FastifyBaseLogger
244
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
245
+ Fn extends preParsingHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | preParsingAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = preParsingHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
252
246
  >(
253
247
  name: 'preParsing',
254
- hook: preParsingHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
255
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
256
-
257
- addHook<
258
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
259
- ContextConfig = ContextConfigDefault,
260
- SchemaCompiler extends FastifySchema = FastifySchema,
261
- Logger extends FastifyBaseLogger = FastifyBaseLogger
262
- >(
263
- name: 'preParsing',
264
- hook: preParsingAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
248
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? preParsingAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : preParsingHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
265
249
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
266
250
 
267
251
  /**
@@ -271,20 +255,11 @@ export interface FastifyInstance<
271
255
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
272
256
  ContextConfig = ContextConfigDefault,
273
257
  SchemaCompiler extends FastifySchema = FastifySchema,
274
- Logger extends FastifyBaseLogger = FastifyBaseLogger
275
- >(
276
- name: 'preValidation',
277
- hook: preValidationHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
278
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
279
-
280
- addHook<
281
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
282
- ContextConfig = ContextConfigDefault,
283
- SchemaCompiler extends FastifySchema = FastifySchema,
284
- Logger extends FastifyBaseLogger = FastifyBaseLogger
258
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
259
+ Fn extends preValidationHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | preValidationAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = preValidationHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
285
260
  >(
286
261
  name: 'preValidation',
287
- hook: preValidationAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
262
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? preValidationAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : preValidationHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
288
263
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
289
264
 
290
265
  /**
@@ -294,20 +269,11 @@ export interface FastifyInstance<
294
269
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
295
270
  ContextConfig = ContextConfigDefault,
296
271
  SchemaCompiler extends FastifySchema = FastifySchema,
297
- Logger extends FastifyBaseLogger = FastifyBaseLogger
298
- >(
299
- name: 'preHandler',
300
- hook: preHandlerHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
301
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
302
-
303
- addHook<
304
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
305
- ContextConfig = ContextConfigDefault,
306
- SchemaCompiler extends FastifySchema = FastifySchema,
307
- Logger extends FastifyBaseLogger = FastifyBaseLogger
272
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
273
+ Fn extends preHandlerHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | preHandlerAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = preHandlerHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
308
274
  >(
309
275
  name: 'preHandler',
310
- hook: preHandlerAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
276
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? preHandlerAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : preHandlerHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
311
277
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
312
278
 
313
279
  /**
@@ -319,21 +285,11 @@ export interface FastifyInstance<
319
285
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
320
286
  ContextConfig = ContextConfigDefault,
321
287
  SchemaCompiler extends FastifySchema = FastifySchema,
322
- Logger extends FastifyBaseLogger = FastifyBaseLogger
288
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
289
+ Fn extends preSerializationHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | preSerializationAsyncHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = preSerializationHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
323
290
  >(
324
291
  name: 'preSerialization',
325
- hook: preSerializationHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
326
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
327
-
328
- addHook<
329
- PreSerializationPayload = unknown,
330
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
331
- ContextConfig = ContextConfigDefault,
332
- SchemaCompiler extends FastifySchema = FastifySchema,
333
- Logger extends FastifyBaseLogger = FastifyBaseLogger
334
- >(
335
- name: 'preSerialization',
336
- hook: preSerializationAsyncHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
292
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? preSerializationAsyncHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : preSerializationHookHandler<PreSerializationPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
337
293
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
338
294
 
339
295
  /**
@@ -345,21 +301,11 @@ export interface FastifyInstance<
345
301
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
346
302
  ContextConfig = ContextConfigDefault,
347
303
  SchemaCompiler extends FastifySchema = FastifySchema,
348
- Logger extends FastifyBaseLogger = FastifyBaseLogger
304
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
305
+ Fn extends onSendHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | onSendAsyncHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = onSendHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
349
306
  >(
350
307
  name: 'onSend',
351
- hook: onSendHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
352
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
353
-
354
- addHook<
355
- OnSendPayload = unknown,
356
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
357
- ContextConfig = ContextConfigDefault,
358
- SchemaCompiler extends FastifySchema = FastifySchema,
359
- Logger extends FastifyBaseLogger = FastifyBaseLogger
360
- >(
361
- name: 'onSend',
362
- hook: onSendAsyncHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
308
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onSendAsyncHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : onSendHookHandler<OnSendPayload, RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
363
309
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
364
310
 
365
311
  /**
@@ -370,20 +316,11 @@ export interface FastifyInstance<
370
316
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
371
317
  ContextConfig = ContextConfigDefault,
372
318
  SchemaCompiler extends FastifySchema = FastifySchema,
373
- Logger extends FastifyBaseLogger = FastifyBaseLogger
374
- >(
375
- name: 'onResponse',
376
- hook: onResponseHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
377
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
378
-
379
- addHook<
380
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
381
- ContextConfig = ContextConfigDefault,
382
- SchemaCompiler extends FastifySchema = FastifySchema,
383
- Logger extends FastifyBaseLogger = FastifyBaseLogger
319
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
320
+ Fn extends onResponseHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | onResponseAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = onResponseHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
384
321
  >(
385
322
  name: 'onResponse',
386
- hook: onResponseAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
323
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onResponseAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : onResponseHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
387
324
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
388
325
 
389
326
  /**
@@ -394,20 +331,11 @@ export interface FastifyInstance<
394
331
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
395
332
  ContextConfig = ContextConfigDefault,
396
333
  SchemaCompiler extends FastifySchema = FastifySchema,
397
- Logger extends FastifyBaseLogger = FastifyBaseLogger
334
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
335
+ Fn extends onTimeoutHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | onTimeoutAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = onTimeoutHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
398
336
  >(
399
337
  name: 'onTimeout',
400
- hook: onTimeoutHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
401
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
402
-
403
- addHook<
404
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
405
- ContextConfig = ContextConfigDefault,
406
- SchemaCompiler extends FastifySchema = FastifySchema,
407
- Logger extends FastifyBaseLogger = FastifyBaseLogger
408
- >(
409
- name: 'onTimeout',
410
- hook: onTimeoutAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
338
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onTimeoutAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : onTimeoutHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
411
339
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
412
340
 
413
341
  /**
@@ -419,20 +347,11 @@ export interface FastifyInstance<
419
347
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
420
348
  ContextConfig = ContextConfigDefault,
421
349
  SchemaCompiler extends FastifySchema = FastifySchema,
422
- Logger extends FastifyBaseLogger = FastifyBaseLogger
423
- >(
424
- name: 'onRequestAbort',
425
- hook: onRequestAbortHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
426
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
427
-
428
- addHook<
429
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
430
- ContextConfig = ContextConfigDefault,
431
- SchemaCompiler extends FastifySchema = FastifySchema,
432
- Logger extends FastifyBaseLogger = FastifyBaseLogger
350
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
351
+ Fn extends onRequestAbortHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> | onRequestAbortAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> = onRequestAbortHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
433
352
  >(
434
353
  name: 'onRequestAbort',
435
- hook: onRequestAbortAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
354
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onRequestAbortAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : onRequestAbortHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> : Fn,
436
355
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
437
356
 
438
357
  /**
@@ -445,20 +364,11 @@ export interface FastifyInstance<
445
364
  RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
446
365
  ContextConfig = ContextConfigDefault,
447
366
  SchemaCompiler extends FastifySchema = FastifySchema,
448
- Logger extends FastifyBaseLogger = FastifyBaseLogger
367
+ Logger extends FastifyBaseLogger = FastifyBaseLogger,
368
+ Fn extends onErrorHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger> | onErrorAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger> = onErrorHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger>
449
369
  >(
450
370
  name: 'onError',
451
- hook: onErrorHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger>
452
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
453
-
454
- addHook<
455
- RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
456
- ContextConfig = ContextConfigDefault,
457
- SchemaCompiler extends FastifySchema = FastifySchema,
458
- Logger extends FastifyBaseLogger = FastifyBaseLogger
459
- >(
460
- name: 'onError',
461
- hook: onErrorAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger>
371
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onErrorAsyncHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger> : onErrorHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, FastifyError, SchemaCompiler, TypeProvider, Logger> : Fn,
462
372
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
463
373
 
464
374
  // Application addHooks
@@ -489,41 +399,40 @@ export interface FastifyInstance<
489
399
  /**
490
400
  * Triggered when fastify.listen() or fastify.ready() is invoked to start the server. It is useful when plugins need a "ready" event, for example to load data before the server start listening for requests.
491
401
  */
492
- addHook(
493
- name: 'onReady',
494
- hook: onReadyHookHandler
495
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
496
-
497
- addHook(
402
+ addHook<
403
+ Fn extends onReadyHookHandler | onReadyAsyncHookHandler = onReadyHookHandler
404
+ >(
498
405
  name: 'onReady',
499
- hook: onReadyAsyncHookHandler,
406
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onReadyAsyncHookHandler : onReadyHookHandler : Fn,
500
407
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
501
408
 
502
409
  /**
503
410
  * Triggered when fastify.close() is invoked to stop the server. It is useful when plugins need a "shutdown" event, for example to close an open connection to a database.
504
411
  */
505
- addHook(
412
+ addHook<
413
+ Fn extends onCloseHookHandler | onCloseAsyncHookHandler = onCloseHookHandler
414
+ >(
506
415
  name: 'onClose',
507
- hook: onCloseHookHandler<RawServer, RawRequest, RawReply, Logger, TypeProvider>
416
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? onCloseAsyncHookHandler : onCloseHookHandler : Fn,
508
417
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
509
418
 
510
- addHook(
511
- name: 'onClose',
512
- hook: onCloseAsyncHookHandler<RawServer, RawRequest, RawReply, Logger>
513
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger>;
514
-
515
419
  /**
516
420
  * Triggered when fastify.close() is invoked to stop the server. It is useful when plugins need to cancel some state to allow the server to close successfully.
517
421
  */
518
- addHook(
422
+ addHook<
423
+ Fn extends preCloseHookHandler | preCloseAsyncHookHandler = preCloseHookHandler
424
+ >(
519
425
  name: 'preClose',
520
- hook: preCloseHookHandler<RawServer, RawRequest, RawReply, Logger, TypeProvider>
426
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? preCloseAsyncHookHandler : preCloseHookHandler : Fn,
521
427
  ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
522
428
 
523
- addHook(
524
- name: 'preClose',
525
- hook: preCloseAsyncHookHandler<RawServer, RawRequest, RawReply, Logger>
526
- ): FastifyInstance<RawServer, RawRequest, RawReply, Logger>;
429
+ addHook<
430
+ K extends ApplicationHook | LifecycleHook,
431
+ Fn extends (...args: any) => Promise<any> | any
432
+ > (
433
+ name: K,
434
+ hook: Fn extends unknown ? Fn extends AsyncFunction ? HookAsyncLookup<K> : HookLookup<K> : Fn
435
+ ): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
527
436
 
528
437
  /**
529
438
  * Set the 404 handler
@@ -50,7 +50,7 @@ export interface FastifyRequest<RouteGeneric extends RouteGenericInterface = Rou
50
50
  // the RequestType (preferred) or swap Logger and RequestType arguments when
51
51
  // creating custom types of FastifyRequest. Related issue #4123
52
52
  > {
53
- id: any;
53
+ id: string;
54
54
  params: RequestType['params']; // deferred inference
55
55
  raw: RawRequest;
56
56
  query: RequestType['query'];
package/types/route.d.ts CHANGED
@@ -45,7 +45,12 @@ export interface RouteShorthandOptions<
45
45
  version?: string;
46
46
  constraints?: { [name: string]: any },
47
47
  prefixTrailingSlash?: 'slash'|'no-slash'|'both';
48
- errorHandler?: (this: FastifyInstance, error: FastifyError, request: FastifyRequest, reply: FastifyReply) => void;
48
+ errorHandler?: (
49
+ this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>,
50
+ error: FastifyError,
51
+ request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, Logger>,
52
+ reply: FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>
53
+ ) => void;
49
54
  childLoggerFactory?: FastifyChildLoggerFactory<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
50
55
  schemaErrorFormatter?: SchemaErrorFormatter;
51
56
 
package/types/schema.d.ts CHANGED
@@ -28,7 +28,7 @@ export interface FastifySchemaValidationError {
28
28
  keyword: string;
29
29
  instancePath: string;
30
30
  schemaPath: string;
31
- params: Record<string, string | string[]>;
31
+ params: Record<string, unknown>;
32
32
  message?: string;
33
33
  }
34
34
 
@@ -7,7 +7,7 @@
7
7
  "strict": true
8
8
  },
9
9
  "include": [
10
- "/test/types/*.test-d.ts",
11
- "/types/*.d.ts"
10
+ "../test/types/**/*.test-d.ts",
11
+ "./**/*.d.ts"
12
12
  ]
13
13
  }