fastify 4.24.2 → 4.25.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.
Files changed (67) hide show
  1. package/README.md +7 -2
  2. package/SECURITY.md +27 -0
  3. package/docs/Guides/Ecosystem.md +18 -6
  4. package/docs/Guides/Getting-Started.md +3 -3
  5. package/docs/Guides/Plugins-Guide.md +2 -2
  6. package/docs/Guides/Style-Guide.md +7 -7
  7. package/docs/Reference/ContentTypeParser.md +2 -0
  8. package/docs/Reference/Errors.md +171 -397
  9. package/docs/Reference/Hooks.md +8 -2
  10. package/docs/Reference/Index.md +2 -0
  11. package/docs/Reference/Reply.md +16 -5
  12. package/docs/Reference/Request.md +1 -1
  13. package/docs/Reference/Routes.md +5 -5
  14. package/docs/Reference/TypeScript.md +1 -1
  15. package/docs/Reference/Warnings.md +77 -0
  16. package/examples/use-plugin.js +2 -0
  17. package/fastify.js +37 -20
  18. package/integration/server.js +2 -0
  19. package/lib/decorate.js +2 -2
  20. package/lib/errors.js +1 -1
  21. package/lib/hooks.js +1 -1
  22. package/lib/pluginUtils.js +10 -1
  23. package/lib/reply.js +5 -5
  24. package/lib/request.js +14 -7
  25. package/lib/route.js +9 -5
  26. package/lib/server.js +20 -27
  27. package/lib/validation.js +5 -5
  28. package/lib/warnings.js +110 -40
  29. package/package.json +4 -4
  30. package/test/buffer.test.js +2 -0
  31. package/test/bundler/esbuild/src/fail-plugin-version.js +2 -0
  32. package/test/bundler/esbuild/src/index.js +2 -0
  33. package/test/bundler/webpack/src/fail-plugin-version.js +2 -0
  34. package/test/bundler/webpack/src/index.js +2 -0
  35. package/test/bundler/webpack/webpack.config.js +2 -0
  36. package/test/close-pipelining.test.js +4 -4
  37. package/test/close.test.js +3 -3
  38. package/test/constrained-routes.test.js +24 -24
  39. package/test/decorator.test.js +27 -22
  40. package/test/default-route.test.js +7 -7
  41. package/test/fastify-instance.test.js +120 -0
  42. package/test/hooks.on-ready.test.js +16 -0
  43. package/test/hooks.test.js +1 -3
  44. package/test/http2/constraint.test.js +1 -1
  45. package/test/internals/errors.test.js +28 -3
  46. package/test/internals/reply.test.js +33 -9
  47. package/test/logger/instantiation.test.js +2 -1
  48. package/test/plugin.4.test.js +28 -0
  49. package/test/register.test.js +5 -5
  50. package/test/reply-trailers.test.js +1 -1
  51. package/test/route.7.test.js +7 -6
  52. package/test/schema-examples.test.js +2 -2
  53. package/test/schema-feature.test.js +11 -11
  54. package/test/server.test.js +51 -0
  55. package/test/types/hooks.test-d.ts +124 -1
  56. package/test/types/instance.test-d.ts +12 -0
  57. package/test/types/logger.test-d.ts +14 -0
  58. package/test/types/reply.test-d.ts +25 -6
  59. package/test/types/request.test-d.ts +3 -2
  60. package/test/types/route.test-d.ts +38 -0
  61. package/test/versioned-routes.test.js +7 -6
  62. package/types/hooks.d.ts +183 -0
  63. package/types/instance.d.ts +12 -12
  64. package/types/reply.d.ts +7 -10
  65. package/types/request.d.ts +2 -1
  66. package/types/route.d.ts +31 -26
  67. package/types/utils.d.ts +10 -0
@@ -86,7 +86,6 @@ object that exposes the following functions and properties:
86
86
  - `.log` - The logger instance of the incoming request.
87
87
  - `.request` - The incoming request.
88
88
  - `.context` - Deprecated, access the [Request's context](./Request.md) property.
89
- - `.routeOptions` - Access the [Request's routeOptions](./Request.md) property.
90
89
 
91
90
  ```js
92
91
  fastify.get('/', options, function (request, reply) {
@@ -666,8 +665,12 @@ fastify.get('/json', options, function (request, reply) {
666
665
  #### Streams
667
666
  <a id="send-streams"></a>
668
667
 
669
- *send* can also handle streams by setting the `'Content-Type'` header to
670
- `'application/octet-stream'`.
668
+ If you are sending a stream and you have not set a `'Content-Type'` header,
669
+ *send* will set it to `'application/octet-stream'`.
670
+
671
+ As noted above, streams are considered to be pre-serialized, so they will be
672
+ sent unmodified without response validation.
673
+
671
674
  ```js
672
675
  fastify.get('/streams', function (request, reply) {
673
676
  const fs = require('node:fs')
@@ -691,6 +694,10 @@ fastify.get('/streams', async function (request, reply) {
691
694
 
692
695
  If you are sending a buffer and you have not set a `'Content-Type'` header,
693
696
  *send* will set it to `'application/octet-stream'`.
697
+
698
+ As noted above, Buffers are considered to be pre-serialized, so they will be
699
+ sent unmodified without response validation.
700
+
694
701
  ```js
695
702
  const fs = require('node:fs')
696
703
  fastify.get('/streams', function (request, reply) {
@@ -714,8 +721,12 @@ fastify.get('/streams', async function (request, reply) {
714
721
  #### TypedArrays
715
722
  <a id="send-typedarrays"></a>
716
723
 
717
- `send` manages TypedArray and sets the `'Content-Type'=application/octet-stream'`
718
- header if not already set.
724
+ `send` manages TypedArray like a Buffer, and sets the `'Content-Type'`
725
+ header to `'application/octet-stream'` if not already set.
726
+
727
+ As noted above, TypedArray/Buffers are considered to be pre-serialized, so they
728
+ will be sent unmodified without response validation.
729
+
719
730
  ```js
720
731
  const fs = require('node:fs')
721
732
  fastify.get('/streams', function (request, reply) {
@@ -161,7 +161,7 @@ for more information on how to compile validation function.
161
161
  This function will compile a validation schema and
162
162
  return a function that can be used to validate data.
163
163
  The function returned (a.k.a. _validation function_) is compiled
164
- by using the provided [`SchemaControler#ValidationCompiler`](./Server.md#schema-controller).
164
+ by using the provided [`SchemaController#ValidationCompiler`](./Server.md#schema-controller).
165
165
  A `WeakMap` is used to cached this, reducing compilation calls.
166
166
 
167
167
  The optional parameter `httpPart`, if provided, is forwarded directly
@@ -715,9 +715,9 @@ arbitrary host matching.
715
715
  fastify.route({
716
716
  method: 'GET',
717
717
  url: '/',
718
- constraints: { host: 'auth.fastify.io' },
718
+ constraints: { host: 'auth.fastify.dev' },
719
719
  handler: function (request, reply) {
720
- reply.send('hello world from auth.fastify.io')
720
+ reply.send('hello world from auth.fastify.dev')
721
721
  }
722
722
  })
723
723
 
@@ -735,10 +735,10 @@ fastify.inject({
735
735
  method: 'GET',
736
736
  url: '/',
737
737
  headers: {
738
- 'Host': 'auth.fastify.io'
738
+ 'Host': 'auth.fastify.dev'
739
739
  }
740
740
  }, (err, res) => {
741
- // => 'hello world from auth.fastify.io'
741
+ // => 'hello world from auth.fastify.dev'
742
742
  })
743
743
  ```
744
744
 
@@ -749,7 +749,7 @@ matching wildcard subdomains (or any other pattern):
749
749
  fastify.route({
750
750
  method: 'GET',
751
751
  url: '/',
752
- constraints: { host: /.*\.fastify\.io/ }, // will match any subdomain of fastify.io
752
+ constraints: { host: /.*\.fastify\.io/ }, // will match any subdomain of fastify.dev
753
753
  handler: function (request, reply) {
754
754
  reply.send('hello world from ' + request.headers.host)
755
755
  }
@@ -256,7 +256,7 @@ can do it as follows:
256
256
 
257
257
  const fastify = Fastify().withTypeProvider<TypeBoxTypeProvider>()
258
258
 
259
- app.post<{ Body: UserType, Reply: UserType }>(
259
+ fastify.post<{ Body: UserType, Reply: UserType }>(
260
260
  '/',
261
261
  {
262
262
  schema: {
@@ -0,0 +1,77 @@
1
+
2
+ <h1 align="center">Fastify</h1>
3
+
4
+ **Table of contents**
5
+ - [Warnings](#warnings)
6
+ - [Warnings In Fastify](#warnings-in-fastify)
7
+ - [Fastify Warning Codes](#fastify-warning-codes)
8
+ - [FSTWRN001](#FSTWRN001)
9
+ - [FSTWRN002](#FSTWRN002)
10
+ - [Fastify Deprecation Codes](#fastify-deprecation-codes)
11
+ - [FSTDEP005](#FSTDEP005)
12
+ - [FSTDEP006](#FSTDEP006)
13
+ - [FSTDEP007](#FSTDEP007)
14
+ - [FSTDEP008](#FSTDEP008)
15
+ - [FSTDEP009](#FSTDEP009)
16
+ - [FSTDEP010](#FSTDEP010)
17
+ - [FSTDEP011](#FSTDEP011)
18
+ - [FSTDEP012](#FSTDEP012)
19
+ - [FSTDEP013](#FSTDEP013)
20
+ - [FSTDEP014](#FSTDEP014)
21
+ - [FSTDEP015](#FSTDEP015)
22
+ - [FSTDEP016](#FSTDEP016)
23
+ - [FSTDEP017](#FSTDEP017)
24
+ - [FSTDEP018](#FSTDEP018)
25
+ - [FSTDEP019](#FSTDEP019)
26
+
27
+
28
+ ## Warnings
29
+
30
+ ### Warnings In Fastify
31
+ Warnings are enabled by default. They can be disabled by using any
32
+ of the following methods:
33
+
34
+ - setting the `NODE_NO_WARNINGS` environment variable to `1`
35
+ - passing the `--no-warnings` flag to the node process
36
+ - setting 'no-warnings' in the `NODE_OPTIONS` environment variable
37
+
38
+ For more information on how to disable warnings, see [node's documentation](https://nodejs.org/api/cli.html).
39
+
40
+ However, disabling warnings is not recommended as it may cause
41
+ potential problems when upgrading Fastify versions.
42
+ Only experienced users should consider disabling warnings.
43
+
44
+ ### Fastify Warning Codes
45
+
46
+ | Code | Description | How to solve | Discussion |
47
+ | ---- | ----------- | ------------ | ---------- |
48
+ | <a id="FSTWRN001">FSTWRN001</a> | The specified schema for a route is missing. This may indicate the schema is not well specified. | Check the schema for the route. | [#4647](https://github.com/fastify/fastify/pull/4647) |
49
+ | <a id="FSTWRN002">FSTWRN002</a> | The %s plugin being registered mixes async and callback styles, which will result in an error in `fastify@5`. | Do not mix async and callback style. | [#5139](https://github.com/fastify/fastify/pull/5139) |
50
+
51
+
52
+ ### Fastify Deprecation Codes
53
+
54
+ Deprecation codes are further supported by the Node.js CLI options:
55
+
56
+ - [--no-deprecation](https://nodejs.org/api/cli.html#--no-deprecation)
57
+ - [--throw-deprecation](https://nodejs.org/api/cli.html#--throw-deprecation)
58
+ - [--trace-deprecation](https://nodejs.org/api/cli.html#--trace-deprecation)
59
+
60
+
61
+ | Code | Description | How to solve | Discussion |
62
+ | ---- | ----------- | ------------ | ---------- |
63
+ | <a id="FSTDEP005">FSTDEP005</a> | You are accessing the deprecated `request.connection` property. | Use `request.socket`. | [#2594](https://github.com/fastify/fastify/pull/2594) |
64
+ | <a id="FSTDEP006">FSTDEP006</a> | You are decorating Request/Reply with a reference type. This reference is shared amongst all requests. | Do not use Arrays/Objects as values when decorating Request/Reply. | [#2688](https://github.com/fastify/fastify/pull/2688) |
65
+ | <a id="FSTDEP007">FSTDEP007</a> | You are trying to set a HEAD route using `exposeHeadRoute` route flag when a sibling route is already set. | Remove `exposeHeadRoutes` or explicitly set `exposeHeadRoutes` to `false` | [#2700](https://github.com/fastify/fastify/pull/2700) |
66
+ | <a id="FSTDEP008">FSTDEP008</a> | You are using route constraints via the route `{version: "..."}` option. | Use `{constraints: {version: "..."}}` option. | [#2682](https://github.com/fastify/fastify/pull/2682) |
67
+ | <a id="FSTDEP009">FSTDEP009</a> | You are using a custom route versioning strategy via the server `{versioning: "..."}` option. | Use `{constraints: {version: "..."}}` option. | [#2682](https://github.com/fastify/fastify/pull/2682) |
68
+ | <a id="FSTDEP010">FSTDEP010</a> | Modifying the `reply.sent` property is deprecated. | Use the `reply.hijack()` method. | [#3140](https://github.com/fastify/fastify/pull/3140) |
69
+ | <a id="FSTDEP011">FSTDEP011</a> | Variadic listen method is deprecated. | Use `.listen(optionsObject)`. | [#3712](https://github.com/fastify/fastify/pull/3712) |
70
+ | <a id="FSTDEP012">FSTDEP012</a> | You are trying to access the deprecated `request.context` property. | Use `request.routeOptions.config` or `request.routeOptions.schema`. | [#4216](https://github.com/fastify/fastify/pull/4216) [#5084](https://github.com/fastify/fastify/pull/5084) |
71
+ | <a id="FSTDEP013">FSTDEP013</a> | Direct return of "trailers" function is deprecated. | Use "callback" or "async-await" for return value. | [#4380](https://github.com/fastify/fastify/pull/4380) |
72
+ | <a id="FSTDEP014">FSTDEP014</a> | You are trying to set/access the default route. This property is deprecated. | Use `setNotFoundHandler` if you want to custom a 404 handler or the wildcard (`*`) to match all routes. | [#4480](https://github.com/fastify/fastify/pull/4480) |
73
+ | <a id="FSTDEP015">FSTDEP015</a> | You are accessing the deprecated `request.routeSchema` property. | Use `request.routeOptions.schema`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
74
+ | <a id="FSTDEP016">FSTDEP016</a> | You are accessing the deprecated `request.routeConfig` property. | Use `request.routeOptions.config`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
75
+ | <a id="FSTDEP017">FSTDEP017</a> | You are accessing the deprecated `request.routerPath` property. | Use `request.routeOptions.url`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
76
+ | <a id="FSTDEP018">FSTDEP018</a> | You are accessing the deprecated `request.routerMethod` property. | Use `request.routeOptions.method`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
77
+ | <a id="FSTDEP019">FSTDEP019</a> | You are accessing the deprecated `reply.context` property. | Use `reply.routeOptions.config` or `reply.routeOptions.schema`. | [#5032](https://github.com/fastify/fastify/pull/5032) [#5084](https://github.com/fastify/fastify/pull/5084) |
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const fastify = require('../fastify')({ logger: true })
2
4
 
3
5
  const opts = {
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '4.24.2'
3
+ const VERSION = '4.25.0'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('node:http')
@@ -47,7 +47,7 @@ const { buildRouting, validateBodyLimitOption } = require('./lib/route')
47
47
  const build404 = require('./lib/fourOhFour')
48
48
  const getSecuredInitialConfig = require('./lib/initialConfigValidation')
49
49
  const override = require('./lib/pluginOverride')
50
- const warning = require('./lib/warnings')
50
+ const { FSTDEP009 } = require('./lib/warnings')
51
51
  const noopSet = require('./lib/noop-set')
52
52
  const {
53
53
  appendStackTrace,
@@ -152,7 +152,7 @@ function fastify (options) {
152
152
 
153
153
  let constraints = options.constraints
154
154
  if (options.versioning) {
155
- warning.emit('FSTDEP009')
155
+ FSTDEP009()
156
156
  constraints = {
157
157
  ...constraints,
158
158
  version: {
@@ -217,7 +217,10 @@ function fastify (options) {
217
217
  [kState]: {
218
218
  listening: false,
219
219
  closing: false,
220
- started: false
220
+ started: false,
221
+ ready: false,
222
+ booting: false,
223
+ readyPromise: null
221
224
  },
222
225
  [kKeepAliveConnections]: keepAliveConnections,
223
226
  [kOptions]: options,
@@ -562,25 +565,43 @@ function fastify (options) {
562
565
  }
563
566
 
564
567
  function ready (cb) {
568
+ if (this[kState].readyPromise !== null) {
569
+ if (cb != null) {
570
+ this[kState].readyPromise.then(() => cb(null, fastify), cb)
571
+ return
572
+ }
573
+
574
+ return this[kState].readyPromise
575
+ }
576
+
565
577
  let resolveReady
566
578
  let rejectReady
567
579
 
568
580
  // run the hooks after returning the promise
569
581
  process.nextTick(runHooks)
570
582
 
583
+ // Create a promise no matter what
584
+ // It will work as a barrier for all the .ready() calls (ensuring single hook execution)
585
+ // as well as a flow control mechanism to chain cbs and further
586
+ // promises
587
+ this[kState].readyPromise = new Promise(function (resolve, reject) {
588
+ resolveReady = resolve
589
+ rejectReady = reject
590
+ })
591
+
571
592
  if (!cb) {
572
- return new Promise(function (resolve, reject) {
573
- resolveReady = resolve
574
- rejectReady = reject
575
- })
593
+ return this[kState].readyPromise
594
+ } else {
595
+ this[kState].readyPromise.then(() => cb(null, fastify), cb)
576
596
  }
577
597
 
578
598
  function runHooks () {
579
599
  // start loading
580
600
  fastify[kAvvioBoot]((err, done) => {
581
- if (err || fastify[kState].started) {
601
+ if (err || fastify[kState].started || fastify[kState].ready || fastify[kState].booting) {
582
602
  manageErr(err)
583
603
  } else {
604
+ fastify[kState].booting = true
584
605
  hookRunnerApplication('onReady', fastify[kAvvioBoot], fastify, manageErr)
585
606
  }
586
607
  done()
@@ -595,18 +616,14 @@ function fastify (options) {
595
616
  ? appendStackTrace(err, new AVVIO_ERRORS_MAP[err.code](err.message))
596
617
  : err
597
618
 
598
- if (cb) {
599
- if (err) {
600
- cb(err)
601
- } else {
602
- cb(undefined, fastify)
603
- }
604
- } else {
605
- if (err) {
606
- return rejectReady(err)
607
- }
608
- resolveReady(fastify)
619
+ if (err) {
620
+ return rejectReady(err)
609
621
  }
622
+
623
+ resolveReady(fastify)
624
+ fastify[kState].booting = false
625
+ fastify[kState].ready = true
626
+ fastify[kState].promise = null
610
627
  }
611
628
  }
612
629
 
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const Fastify = require('../fastify')
2
4
 
3
5
  const fastify = Fastify()
package/lib/decorate.js CHANGED
@@ -16,7 +16,7 @@ const {
16
16
  FST_ERR_DEC_DEPENDENCY_INVALID_TYPE
17
17
  } = require('./errors')
18
18
 
19
- const warning = require('./warnings')
19
+ const { FSTDEP006 } = require('./warnings')
20
20
 
21
21
  function decorate (instance, name, fn, dependencies) {
22
22
  if (Object.prototype.hasOwnProperty.call(instance, name)) {
@@ -58,7 +58,7 @@ function decorateConstructor (konstructor, name, fn, dependencies) {
58
58
 
59
59
  function checkReferenceType (name, fn) {
60
60
  if (typeof fn === 'object' && fn && !(typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
61
- warning.emit('FSTDEP006', name)
61
+ FSTDEP006(name)
62
62
  }
63
63
  }
64
64
 
package/lib/errors.js CHANGED
@@ -179,7 +179,7 @@ const codes = {
179
179
  */
180
180
  FST_ERR_MISSING_MIDDLEWARE: createError(
181
181
  'FST_ERR_MISSING_MIDDLEWARE',
182
- 'You must register a plugin for handling middlewares, visit fastify.io/docs/latest/Reference/Middleware/ for more info.',
182
+ 'You must register a plugin for handling middlewares, visit fastify.dev/docs/latest/Reference/Middleware/ for more info.',
183
183
  500
184
184
  ),
185
185
 
package/lib/hooks.js CHANGED
@@ -331,7 +331,7 @@ function preParsingHookRunner (functions, request, reply, cb) {
331
331
  return
332
332
  }
333
333
 
334
- if (typeof newPayload !== 'undefined') {
334
+ if (newPayload !== undefined) {
335
335
  request[kRequestPayloadStream] = newPayload
336
336
  }
337
337
 
@@ -11,6 +11,7 @@ const {
11
11
  FST_ERR_PLUGIN_VERSION_MISMATCH,
12
12
  FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE
13
13
  } = require('./errors')
14
+ const { FSTWRN002 } = require('./warnings.js')
14
15
 
15
16
  function getMeta (fn) {
16
17
  return fn[Symbol.for('plugin-meta')]
@@ -132,10 +133,18 @@ function registerPluginName (fn) {
132
133
  const name = meta.name
133
134
  if (!name) return
134
135
  this[kRegisteredPlugins].push(name)
136
+ return name
137
+ }
138
+
139
+ function checkPluginHealthiness (fn, pluginName = 'anonymous') {
140
+ if (fn.constructor.name === 'AsyncFunction' && fn.length === 3) {
141
+ FSTWRN002(pluginName)
142
+ }
135
143
  }
136
144
 
137
145
  function registerPlugin (fn) {
138
- registerPluginName.call(this, fn)
146
+ const pluginName = registerPluginName.call(this, fn)
147
+ checkPluginHealthiness.call(this, fn, pluginName)
139
148
  checkVersion.call(this, fn)
140
149
  checkDecorators.call(this, fn)
141
150
  checkDependencies.call(this, fn)
package/lib/reply.js CHANGED
@@ -53,7 +53,7 @@ const {
53
53
  FST_ERR_MISSING_SERIALIZATION_FN,
54
54
  FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN
55
55
  } = require('./errors')
56
- const warning = require('./warnings')
56
+ const { FSTDEP010, FSTDEP013, FSTDEP019 } = require('./warnings')
57
57
 
58
58
  function Reply (res, request, log) {
59
59
  this.raw = res
@@ -80,7 +80,7 @@ Object.defineProperties(Reply.prototype, {
80
80
  // Is temporary to avoid constant conflicts between `next` and `main`
81
81
  context: {
82
82
  get () {
83
- warning.emit('FSTDEP019')
83
+ FSTDEP019()
84
84
  return this.request[kRouteContext]
85
85
  }
86
86
  },
@@ -96,7 +96,7 @@ Object.defineProperties(Reply.prototype, {
96
96
  return (this[kReplyHijacked] || this.raw.writableEnded) === true
97
97
  },
98
98
  set (value) {
99
- warning.emit('FSTDEP010')
99
+ FSTDEP010()
100
100
 
101
101
  if (value !== true) {
102
102
  throw new FST_ERR_REP_SENT_VALUE()
@@ -164,7 +164,7 @@ Reply.prototype.send = function (payload) {
164
164
  if (hasContentType === false) {
165
165
  this[kReplyHeaders]['content-type'] = CONTENT_TYPE.OCTET
166
166
  }
167
- const payloadToSend = Buffer.isBuffer(payload) ? payload : Buffer.from(payload.buffer)
167
+ const payloadToSend = Buffer.isBuffer(payload) ? payload : Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength)
168
168
  onSendHook(this, payloadToSend)
169
169
  return this
170
170
  }
@@ -748,7 +748,7 @@ function sendTrailer (payload, res, reply) {
748
748
  result.then((v) => cb(null, v), cb)
749
749
  } else if (result !== null && result !== undefined) {
750
750
  // TODO: should be removed in fastify@5
751
- warning.emit('FSTDEP013')
751
+ FSTDEP013()
752
752
  cb(null, result)
753
753
  }
754
754
  }
package/lib/request.js CHANGED
@@ -2,7 +2,14 @@
2
2
 
3
3
  const proxyAddr = require('proxy-addr')
4
4
  const semver = require('semver')
5
- const warning = require('./warnings')
5
+ const {
6
+ FSTDEP005,
7
+ FSTDEP012,
8
+ FSTDEP015,
9
+ FSTDEP016,
10
+ FSTDEP017,
11
+ FSTDEP018
12
+ } = require('./warnings')
6
13
  const {
7
14
  kHasBeenDecorated,
8
15
  kSchemaBody,
@@ -166,13 +173,13 @@ Object.defineProperties(Request.prototype, {
166
173
  },
167
174
  context: {
168
175
  get () {
169
- warning.emit('FSTDEP012')
176
+ FSTDEP012()
170
177
  return this[kRouteContext]
171
178
  }
172
179
  },
173
180
  routerPath: {
174
181
  get () {
175
- warning.emit('FSTDEP017')
182
+ FSTDEP017()
176
183
  return this[kRouteContext].config?.url
177
184
  }
178
185
  },
@@ -208,19 +215,19 @@ Object.defineProperties(Request.prototype, {
208
215
  },
209
216
  routerMethod: {
210
217
  get () {
211
- warning.emit('FSTDEP018')
218
+ FSTDEP018()
212
219
  return this[kRouteContext].config?.method
213
220
  }
214
221
  },
215
222
  routeConfig: {
216
223
  get () {
217
- warning.emit('FSTDEP016')
224
+ FSTDEP016()
218
225
  return this[kRouteContext][kPublicRouteContext]?.config
219
226
  }
220
227
  },
221
228
  routeSchema: {
222
229
  get () {
223
- warning.emit('FSTDEP015')
230
+ FSTDEP015()
224
231
  return this[kRouteContext][kPublicRouteContext].schema
225
232
  }
226
233
  },
@@ -233,7 +240,7 @@ Object.defineProperties(Request.prototype, {
233
240
  get () {
234
241
  /* istanbul ignore next */
235
242
  if (semver.gte(process.versions.node, '13.0.0')) {
236
- warning.emit('FSTDEP005')
243
+ FSTDEP005()
237
244
  }
238
245
  return this.raw.connection
239
246
  }
package/lib/route.js CHANGED
@@ -7,7 +7,11 @@ const { onRequestAbortHookRunner, lifecycleHooks, preParsingHookRunner, onTimeou
7
7
  const { supportedMethods } = require('./httpMethods')
8
8
  const { normalizeSchema } = require('./schemas')
9
9
  const { parseHeadOnSendHandlers } = require('./headRoute')
10
- const warning = require('./warnings')
10
+ const {
11
+ FSTDEP007,
12
+ FSTDEP008,
13
+ FSTDEP014
14
+ } = require('./warnings')
11
15
 
12
16
  const {
13
17
  compileSchemasForValidation,
@@ -100,11 +104,11 @@ function buildRouting (options) {
100
104
  hasRoute,
101
105
  prepareRoute,
102
106
  getDefaultRoute: function () {
103
- warning.emit('FSTDEP014')
107
+ FSTDEP014()
104
108
  return router.defaultRoute
105
109
  },
106
110
  setDefaultRoute: function (defaultRoute) {
107
- warning.emit('FSTDEP014')
111
+ FSTDEP014()
108
112
  if (typeof defaultRoute !== 'function') {
109
113
  throw new FST_ERR_DEFAULT_ROUTE_INVALID_TYPE()
110
114
  }
@@ -324,7 +328,7 @@ function buildRouting (options) {
324
328
  })
325
329
 
326
330
  if (opts.version) {
327
- warning.emit('FSTDEP008')
331
+ FSTDEP008()
328
332
  constraints.version = opts.version
329
333
  }
330
334
 
@@ -417,7 +421,7 @@ function buildRouting (options) {
417
421
  const onSendHandlers = parseHeadOnSendHandlers(headOpts.onSend)
418
422
  prepareRoute.call(this, { method: 'HEAD', url: path, options: { ...headOpts, onSend: onSendHandlers }, isFastify: true })
419
423
  } else if (hasHEADHandler && exposeHeadRoute) {
420
- warning.emit('FSTDEP007')
424
+ FSTDEP007()
421
425
  }
422
426
  }
423
427
  }
package/lib/server.js CHANGED
@@ -4,7 +4,7 @@ const http = require('node:http')
4
4
  const https = require('node:https')
5
5
  const dns = require('node:dns')
6
6
 
7
- const warnings = require('./warnings')
7
+ const { FSTDEP011 } = require('./warnings')
8
8
  const { kState, kOptions, kServerBindings } = require('./symbols')
9
9
  const { onListenHookRunner } = require('./hooks')
10
10
  const {
@@ -36,12 +36,12 @@ function createServer (options, httpHandler) {
36
36
  if (arguments.length === 0) {
37
37
  listenOptions = normalizeListenArgs([])
38
38
  } else if (arguments.length > 0 && (firstArgType !== '[object Object]' && firstArgType !== '[object Function]')) {
39
- warnings.emit('FSTDEP011')
39
+ FSTDEP011()
40
40
  listenOptions = normalizeListenArgs(Array.from(arguments))
41
41
  cb = listenOptions.cb
42
42
  } else if (args.length > 1) {
43
43
  // `.listen(obj, a, ..., n, callback )`
44
- warnings.emit('FSTDEP011')
44
+ FSTDEP011()
45
45
  // Deal with `.listen(port, host, backlog, [cb])`
46
46
  const hostPath = listenOptions.path ? [listenOptions.path] : [listenOptions.port ?? 0, listenOptions.host ?? 'localhost']
47
47
  Object.assign(listenOptions, normalizeListenArgs([...hostPath, ...args]))
@@ -163,29 +163,6 @@ function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, o
163
163
  /* istanbul ignore next: the else won't be taken unless listening fails */
164
164
  if (!_ignoreErr) {
165
165
  this[kServerBindings].push(secondaryServer)
166
- // Due to the nature of the feature is not possible to know
167
- // ahead of time the number of bindings that will be made.
168
- // For instance, each binding is hooked to be closed at their own
169
- // pace through the `onClose` hook.
170
- // It also allows them to handle possible connections already
171
- // attached to them if any.
172
- /* c8 ignore next 20 */
173
- this.onClose((instance, done) => {
174
- if (instance[kState].listening) {
175
- // No new TCP connections are accepted
176
- // We swallow any error from the secondary
177
- // server
178
- secondaryServer.close(() => done())
179
- if (serverOpts.forceCloseConnections === 'idle') {
180
- // Not needed in Node 19
181
- secondaryServer.closeIdleConnections()
182
- } else if (typeof secondaryServer.closeAllConnections === 'function' && serverOpts.forceCloseConnections) {
183
- secondaryServer.closeAllConnections()
184
- }
185
- } else {
186
- done()
187
- }
188
- })
189
166
  }
190
167
 
191
168
  if (bound === binding) {
@@ -196,7 +173,23 @@ function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, o
196
173
  })
197
174
 
198
175
  const secondaryServer = getServerInstance(serverOpts, httpHandler)
199
- const closeSecondary = () => { secondaryServer.close(() => { }) }
176
+ const closeSecondary = () => {
177
+ // To avoid fall into situations where the close of the
178
+ // secondary server is triggered before the preClose hook
179
+ // is done running, we better wait until the main server
180
+ // is closed.
181
+ // No new TCP connections are accepted
182
+ // We swallow any error from the secondary
183
+ // server
184
+ secondaryServer.close(() => {})
185
+ if (serverOpts.forceCloseConnections === 'idle') {
186
+ // Not needed in Node 19
187
+ secondaryServer.closeIdleConnections()
188
+ } else if (typeof secondaryServer.closeAllConnections === 'function' && serverOpts.forceCloseConnections) {
189
+ secondaryServer.closeAllConnections()
190
+ }
191
+ }
192
+
200
193
  secondaryServer.on('upgrade', mainServer.emit.bind(mainServer, 'upgrade'))
201
194
  mainServer.on('unref', closeSecondary)
202
195
  mainServer.on('close', closeSecondary)
package/lib/validation.js CHANGED
@@ -13,7 +13,7 @@ const {
13
13
  FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX
14
14
  } = require('./errors')
15
15
 
16
- const warning = require('./warnings')
16
+ const { FSTWRN001 } = require('./warnings')
17
17
 
18
18
  function compileSchemasForSerialization (context, compile) {
19
19
  if (!context.schema || !context.schema.response) {
@@ -83,25 +83,25 @@ function compileSchemasForValidation (context, compile, isCustom) {
83
83
  }
84
84
  context[headersSchema] = compile({ schema: headersSchemaLowerCase, method, url, httpPart: 'headers' })
85
85
  } else if (Object.prototype.hasOwnProperty.call(schema, 'headers')) {
86
- warning.emit('FSTWRN001', 'headers', method, url)
86
+ FSTWRN001('headers', method, url)
87
87
  }
88
88
 
89
89
  if (schema.body) {
90
90
  context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
91
91
  } else if (Object.prototype.hasOwnProperty.call(schema, 'body')) {
92
- warning.emit('FSTWRN001', 'body', method, url)
92
+ FSTWRN001('body', method, url)
93
93
  }
94
94
 
95
95
  if (schema.querystring) {
96
96
  context[querystringSchema] = compile({ schema: schema.querystring, method, url, httpPart: 'querystring' })
97
97
  } else if (Object.prototype.hasOwnProperty.call(schema, 'querystring')) {
98
- warning.emit('FSTWRN001', 'querystring', method, url)
98
+ FSTWRN001('querystring', method, url)
99
99
  }
100
100
 
101
101
  if (schema.params) {
102
102
  context[paramsSchema] = compile({ schema: schema.params, method, url, httpPart: 'params' })
103
103
  } else if (Object.prototype.hasOwnProperty.call(schema, 'params')) {
104
- warning.emit('FSTWRN001', 'params', method, url)
104
+ FSTWRN001('params', method, url)
105
105
  }
106
106
  }
107
107