fastify 5.0.0 → 5.2.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 (201) hide show
  1. package/.borp.yaml +3 -0
  2. package/.vscode/settings.json +22 -0
  3. package/README.md +12 -7
  4. package/docs/Guides/Database.md +15 -15
  5. package/docs/Guides/Detecting-When-Clients-Abort.md +28 -28
  6. package/docs/Guides/Ecosystem.md +14 -15
  7. package/docs/Guides/Index.md +1 -1
  8. package/docs/Guides/Migration-Guide-V4.md +11 -11
  9. package/docs/Guides/Migration-Guide-V5.md +133 -9
  10. package/docs/Guides/Plugins-Guide.md +1 -1
  11. package/docs/Guides/Prototype-Poisoning.md +3 -3
  12. package/docs/Guides/Recommendations.md +9 -9
  13. package/docs/Guides/Serverless.md +5 -5
  14. package/docs/Guides/Testing.md +58 -57
  15. package/docs/Guides/Write-Plugin.md +2 -2
  16. package/docs/Guides/Write-Type-Provider.md +3 -3
  17. package/docs/Reference/ContentTypeParser.md +4 -4
  18. package/docs/Reference/Decorators.md +2 -2
  19. package/docs/Reference/Errors.md +3 -3
  20. package/docs/Reference/Hooks.md +7 -7
  21. package/docs/Reference/LTS.md +8 -0
  22. package/docs/Reference/Logging.md +5 -4
  23. package/docs/Reference/Reply.md +55 -58
  24. package/docs/Reference/Request.md +49 -42
  25. package/docs/Reference/Routes.md +16 -13
  26. package/docs/Reference/Server.md +32 -28
  27. package/docs/Reference/TypeScript.md +9 -9
  28. package/docs/Reference/Validation-and-Serialization.md +5 -5
  29. package/examples/typescript-server.ts +1 -1
  30. package/fastify.d.ts +14 -5
  31. package/fastify.js +8 -6
  32. package/lib/contentTypeParser.js +9 -7
  33. package/lib/context.js +1 -2
  34. package/lib/error-handler.js +9 -9
  35. package/lib/errors.js +1 -1
  36. package/lib/fourOhFour.js +1 -1
  37. package/lib/hooks.js +4 -1
  38. package/lib/{logger.js → logger-factory.js} +70 -122
  39. package/lib/logger-pino.js +68 -0
  40. package/lib/pluginOverride.js +1 -1
  41. package/lib/pluginUtils.js +2 -2
  42. package/lib/reply.js +4 -5
  43. package/lib/request.js +16 -9
  44. package/lib/route.js +23 -22
  45. package/lib/validation.js +2 -2
  46. package/package.json +13 -15
  47. package/test/404s.test.js +675 -629
  48. package/test/500s.test.js +72 -63
  49. package/test/{allowUnsafeRegex.test.js → allow-unsafe-regex.test.js} +30 -26
  50. package/test/als.test.js +48 -45
  51. package/test/async-await.test.js +148 -134
  52. package/test/async-dispose.test.js +4 -5
  53. package/test/async_hooks.test.js +30 -28
  54. package/test/{bodyLimit.test.js → body-limit.test.js} +61 -58
  55. package/test/buffer.test.js +9 -10
  56. package/test/build/error-serializer.test.js +3 -4
  57. package/test/build/version.test.js +2 -3
  58. package/test/build-certificate.js +1 -1
  59. package/test/bundler/README.md +5 -5
  60. package/test/bundler/esbuild/bundler-test.js +10 -9
  61. package/test/bundler/webpack/bundler-test.js +10 -9
  62. package/test/case-insensitive.test.js +31 -28
  63. package/test/chainable.test.js +4 -5
  64. package/test/check.test.js +8 -10
  65. package/test/{childLoggerFactory.test.js → child-logger-factory.test.js} +56 -19
  66. package/test/client-timeout.test.js +5 -5
  67. package/test/close-pipelining.test.js +6 -8
  68. package/test/conditional-pino.test.js +47 -0
  69. package/test/{connectionTimeout.test.js → connection-timeout.test.js} +10 -11
  70. package/test/constrained-routes.test.js +243 -236
  71. package/test/content-length.test.js +53 -68
  72. package/test/content-parser.test.js +186 -158
  73. package/test/content-type.test.js +8 -9
  74. package/test/context-config.test.js +44 -54
  75. package/test/custom-http-server.test.js +16 -20
  76. package/test/custom-parser.5.test.js +32 -32
  77. package/test/diagnostics-channel/404.test.js +15 -15
  78. package/test/diagnostics-channel/async-delay-request.test.js +25 -25
  79. package/test/diagnostics-channel/async-request.test.js +24 -24
  80. package/test/diagnostics-channel/error-before-handler.test.js +4 -5
  81. package/test/diagnostics-channel/error-request.test.js +19 -19
  82. package/test/diagnostics-channel/error-status.test.js +8 -8
  83. package/test/diagnostics-channel/init.test.js +6 -7
  84. package/test/diagnostics-channel/sync-delay-request.test.js +16 -16
  85. package/test/diagnostics-channel/sync-request-reply.test.js +16 -16
  86. package/test/diagnostics-channel/sync-request.test.js +19 -19
  87. package/test/encapsulated-child-logger-factory.test.js +8 -8
  88. package/test/encapsulated-error-handler.test.js +20 -20
  89. package/test/esm/errorCodes.test.mjs +5 -5
  90. package/test/esm/esm.test.mjs +3 -3
  91. package/test/esm/named-exports.mjs +3 -3
  92. package/test/esm/other.mjs +2 -2
  93. package/test/fastify-instance.test.js +33 -34
  94. package/test/{findRoute.test.js → find-route.test.js} +11 -10
  95. package/test/fluent-schema.test.js +33 -36
  96. package/test/handler-context.test.js +11 -11
  97. package/test/has-route.test.js +12 -15
  98. package/test/header-overflow.test.js +13 -12
  99. package/test/hooks.on-ready.test.js +2 -2
  100. package/test/hooks.test.js +25 -25
  101. package/test/http-methods/copy.test.js +22 -24
  102. package/test/http-methods/custom-http-methods.test.js +24 -21
  103. package/test/http-methods/get.test.js +97 -84
  104. package/test/http-methods/head.test.js +63 -57
  105. package/test/http-methods/lock.test.js +21 -20
  106. package/test/http-methods/mkcalendar.test.js +31 -27
  107. package/test/http-methods/mkcol.test.js +10 -10
  108. package/test/http-methods/move.test.js +11 -11
  109. package/test/http-methods/propfind.test.js +32 -27
  110. package/test/http-methods/proppatch.test.js +21 -19
  111. package/test/http-methods/report.test.js +32 -27
  112. package/test/http-methods/search.test.js +52 -47
  113. package/test/http-methods/trace.test.js +3 -4
  114. package/test/http-methods/unlock.test.js +10 -10
  115. package/test/http2/closing.test.js +50 -58
  116. package/test/http2/constraint.test.js +47 -50
  117. package/test/http2/head.test.js +18 -19
  118. package/test/http2/missing-http2-module.test.js +4 -5
  119. package/test/http2/plain.test.js +31 -31
  120. package/test/http2/secure-with-fallback.test.js +61 -61
  121. package/test/http2/secure.test.js +28 -31
  122. package/test/http2/unknown-http-method.test.js +13 -14
  123. package/test/https/custom-https-server.test.js +6 -7
  124. package/test/https/https.test.js +78 -78
  125. package/test/imports.test.js +5 -6
  126. package/test/internals/all.test.js +8 -11
  127. package/test/internals/{contentTypeParser.test.js → content-type-parser.test.js} +5 -6
  128. package/test/internals/context.test.js +9 -11
  129. package/test/internals/decorator.test.js +20 -21
  130. package/test/internals/errors.test.js +427 -427
  131. package/test/internals/{handleRequest.test.js → handle-request.test.js} +53 -42
  132. package/test/internals/{hookRunner.test.js → hook-runner.test.js} +99 -100
  133. package/test/internals/hooks.test.js +31 -35
  134. package/test/internals/{initialConfig.test.js → initial-config.test.js} +92 -80
  135. package/test/internals/logger.test.js +28 -28
  136. package/test/internals/plugin.test.js +17 -18
  137. package/test/internals/reply-serialize.test.js +106 -106
  138. package/test/internals/reply.test.js +620 -585
  139. package/test/internals/{reqIdGenFactory.test.js → req-id-gen-factory.test.js} +31 -31
  140. package/test/internals/request-validate.test.js +218 -221
  141. package/test/internals/request.test.js +225 -107
  142. package/test/internals/server.test.js +15 -12
  143. package/test/internals/validation.test.js +35 -36
  144. package/test/{keepAliveTimeout.test.js → keep-alive-timeout.test.js} +9 -10
  145. package/test/listen.5.test.js +9 -9
  146. package/test/{maxRequestsPerSocket.test.js → max-requests-per-socket.test.js} +30 -30
  147. package/test/middleware.test.js +4 -5
  148. package/test/noop-set.test.js +5 -5
  149. package/test/post-empty-body.test.js +18 -11
  150. package/test/pretty-print.test.js +59 -49
  151. package/test/proto-poisoning.test.js +42 -37
  152. package/test/reply-code.test.js +34 -32
  153. package/test/{reply-earlyHints.test.js → reply-early-hints.test.js} +21 -19
  154. package/test/request-error.test.js +122 -0
  155. package/test/request-header-host.test.js +339 -0
  156. package/test/request-id.test.js +31 -25
  157. package/test/{requestTimeout.test.js → request-timeout.test.js} +11 -11
  158. package/test/route.1.test.js +79 -72
  159. package/test/route.2.test.js +17 -16
  160. package/test/route.3.test.js +32 -27
  161. package/test/route.4.test.js +21 -25
  162. package/test/route.5.test.js +45 -64
  163. package/test/route.6.test.js +70 -89
  164. package/test/route.7.test.js +61 -65
  165. package/test/route.8.test.js +80 -18
  166. package/test/router-options.test.js +80 -77
  167. package/test/same-shape.test.js +5 -5
  168. package/test/schema-examples.test.js +72 -38
  169. package/test/serialize-response.test.js +9 -10
  170. package/test/server.test.js +75 -78
  171. package/test/set-error-handler.test.js +2 -3
  172. package/test/stream-serializers.test.js +10 -7
  173. package/test/sync-routes.test.js +18 -18
  174. package/test/test-reporter.mjs +68 -0
  175. package/test/trust-proxy.test.js +51 -45
  176. package/test/type-provider.test.js +8 -6
  177. package/test/types/content-type-parser.test-d.ts +1 -1
  178. package/test/types/fastify.test-d.ts +16 -4
  179. package/test/types/hooks.test-d.ts +2 -1
  180. package/test/types/instance.test-d.ts +13 -13
  181. package/test/types/logger.test-d.ts +2 -2
  182. package/test/types/plugin.test-d.ts +17 -9
  183. package/test/types/register.test-d.ts +22 -6
  184. package/test/types/reply.test-d.ts +1 -1
  185. package/test/types/route.test-d.ts +34 -4
  186. package/test/types/serverFactory.test-d.ts +1 -1
  187. package/test/types/type-provider.test-d.ts +1 -1
  188. package/test/url-rewriting.test.js +35 -38
  189. package/test/{useSemicolonDelimiter.test.js → use-semicolon-delimiter.test.js} +30 -30
  190. package/test/validation-error-handling.test.js +259 -285
  191. package/test/versioned-routes.test.js +126 -113
  192. package/test/web-api.test.js +48 -37
  193. package/test/{wrapThenable.test.js → wrap-thenable.test.js} +10 -9
  194. package/types/hooks.d.ts +2 -1
  195. package/types/instance.d.ts +9 -2
  196. package/types/register.d.ts +12 -3
  197. package/types/reply.d.ts +1 -1
  198. package/types/request.d.ts +2 -6
  199. package/types/serverFactory.d.ts +3 -3
  200. package/types/utils.d.ts +13 -5
  201. package/test/types/import.js +0 -2
@@ -8,7 +8,7 @@
8
8
  <a id="pp"></a>
9
9
 
10
10
  Based on the article by Eran Hammer,the issue is created by a web security bug.
11
- It is also a perfect illustration of the efforts required to maintain
11
+ It is also a perfect illustration of the efforts required to maintain
12
12
  open-source software and the limitations of existing communication channels.
13
13
 
14
14
  But first, if we use a JavaScript framework to process incoming JSON data, take
@@ -16,7 +16,7 @@ a moment to read up on [Prototype Poisoning](https://medium.com/intrinsic/javasc
16
16
  in general, and the specific
17
17
  [technical details](https://github.com/hapijs/hapi/issues/3916) of this issue.
18
18
  This could be a critical issue so, we might need to verify your own code first.
19
- It focuses on specific framework however, any solution that uses `JSON.parse()`
19
+ It focuses on specific framework however, any solution that uses `JSON.parse()`
20
20
  to process external data is potentially at risk.
21
21
 
22
22
  ### BOOM
@@ -42,7 +42,7 @@ defect a validation library can have.
42
42
 
43
43
  To understand this, we need to understand how JavaScript works a bit.
44
44
  Every object in JavaScript can have a prototype. It is a set of methods and
45
- properties it "inherits" from another object. I have put inherits in quotes
45
+ properties it "inherits" from another object. I have put inherits in quotes
46
46
  because JavaScript isn't really an object-oriented language. It is a prototype-
47
47
  based object-oriented language.
48
48
 
@@ -307,22 +307,22 @@ readinessProbe:
307
307
  ## Capacity Planning For Production
308
308
  <a id="capacity"></a>
309
309
 
310
- In order to rightsize the production environment for your Fastify application,
311
- it is highly recommended that you perform your own measurements against
310
+ In order to rightsize the production environment for your Fastify application,
311
+ it is highly recommended that you perform your own measurements against
312
312
  different configurations of the environment, which may
313
313
  use real CPU cores, virtual CPU cores (vCPU), or even fractional
314
314
  vCPU cores. We will use the term vCPU throughout this
315
315
  recommendation to represent any CPU type.
316
316
 
317
- Tools such as [k6](https://github.com/grafana/k6)
317
+ Tools such as [k6](https://github.com/grafana/k6)
318
318
  or [autocannon](https://github.com/mcollina/autocannon) can be used for
319
319
  conducting the necessary performance tests.
320
320
 
321
321
  That said, you may also consider the following as a rule of thumb:
322
322
 
323
- * To have the lowest possible latency, 2 vCPU are recommended per app
324
- instance (e.g., a k8s pod). The second vCPU will mostly be used by the
325
- garbage collector (GC) and libuv threadpool. This will minimize the latency
323
+ * To have the lowest possible latency, 2 vCPU are recommended per app
324
+ instance (e.g., a k8s pod). The second vCPU will mostly be used by the
325
+ garbage collector (GC) and libuv threadpool. This will minimize the latency
326
326
  for your users, as well as the memory usage, as the GC will be run more
327
327
  frequently. Also, the main thread won't have to stop to let the GC run.
328
328
 
@@ -330,7 +330,7 @@ frequently. Also, the main thread won't have to stop to let the GC run.
330
330
  requests per second per vCPU available), consider using a smaller amount of vCPUs
331
331
  per app instance. It is totally fine to run Node.js applications with 1 vCPU.
332
332
 
333
- * You may experiment with an even smaller amount of vCPU, which may provide
333
+ * You may experiment with an even smaller amount of vCPU, which may provide
334
334
  even better throughput in certain use-cases. There are reports of API gateway
335
335
  solutions working well with 100m-200m vCPU in Kubernetes.
336
336
 
@@ -347,7 +347,7 @@ would be exposing metrics endpoints on a separate port,
347
347
  to prevent public access, when using a reverse proxy or an ingress
348
348
  firewall is not an option.
349
349
 
350
- It is perfectly fine to spin up several Fastify instances within the same
351
- Node.js process and run them concurrently, even in high load systems.
350
+ It is perfectly fine to spin up several Fastify instances within the same
351
+ Node.js process and run them concurrently, even in high load systems.
352
352
  Each Fastify instance only generates as much load as the traffic it receives,
353
353
  plus the memory used for that Fastify instance.
@@ -36,10 +36,10 @@ snippet of code.
36
36
 
37
37
  To integrate with AWS, you have two choices of library:
38
38
 
39
- - Using [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify)
39
+ - Using [@fastify/aws-lambda](https://github.com/fastify/aws-lambda-fastify)
40
40
  which only adds API Gateway support but has heavy optimizations for fastify.
41
- - Using [@h4ad/serverless-adapter](https://github.com/H4ad/serverless-adapter)
42
- which is a little slower as it creates an HTTP request for each AWS event but
41
+ - Using [@h4ad/serverless-adapter](https://github.com/H4ad/serverless-adapter)
42
+ which is a little slower as it creates an HTTP request for each AWS event but
43
43
  has support for more AWS services such as: AWS SQS, AWS SNS and others.
44
44
 
45
45
  So you can decide which option is best for you, but you can test both libraries.
@@ -263,7 +263,7 @@ curl -X POST https://$GOOGLE_REGION-$GOOGLE_PROJECT.cloudfunctions.net/me \
263
263
 
264
264
  ## Google Firebase Functions
265
265
 
266
- Follow this guide if you want to use Fastify as the HTTP framework for
266
+ Follow this guide if you want to use Fastify as the HTTP framework for
267
267
  Firebase Functions instead of the vanilla JavaScript router provided with
268
268
  `onRequest(async (req, res) => {}`.
269
269
 
@@ -280,7 +280,7 @@ const { onRequest } = require("firebase-functions/v2/https")
280
280
  ### Creation of Fastify instance
281
281
 
282
282
  Create the Fastify instance and encapsulate the returned application instance
283
- in a function which will register routes, await the server's processing of
283
+ in a function which will register routes, await the server's processing of
284
284
  plugins, hooks and other settings. As follows:
285
285
 
286
286
  ```js
@@ -5,15 +5,15 @@
5
5
 
6
6
  Testing is one of the most important parts of developing an application. Fastify
7
7
  is very flexible when it comes to testing and is compatible with most testing
8
- frameworks (such as [Tap](https://www.npmjs.com/package/tap), which is used in
9
- the examples below).
8
+ frameworks (such as [Node Test Runner](https://nodejs.org/api/test.html),
9
+ which is used in the examples below).
10
10
 
11
11
  ## Application
12
12
 
13
13
  Let's `cd` into a fresh directory called 'testing-example' and type `npm init
14
14
  -y` in our terminal.
15
15
 
16
- Run `npm i fastify && npm i tap pino-pretty -D`
16
+ Run `npm i fastify && npm i pino-pretty -D`
17
17
 
18
18
  ### Separating concerns makes testing easy
19
19
 
@@ -113,24 +113,25 @@ Now we can replace our `console.log` calls with actual tests!
113
113
 
114
114
  In your `package.json` change the "test" script to:
115
115
 
116
- `"test": "tap --reporter=list --watch"`
116
+ `"test": "node --test --watch"`
117
117
 
118
118
  **app.test.js**:
119
119
 
120
120
  ```js
121
121
  'use strict'
122
122
 
123
- const { test } = require('tap')
123
+ const { test } = require('node:test')
124
124
  const build = require('./app')
125
125
 
126
126
  test('requests the "/" route', async t => {
127
+ t.plan(1)
127
128
  const app = build()
128
129
 
129
130
  const response = await app.inject({
130
131
  method: 'GET',
131
132
  url: '/'
132
133
  })
133
- t.equal(response.statusCode, 200, 'returns a status code of 200')
134
+ t.assert.strictEqual(response.statusCode, 200, 'returns a status code of 200')
134
135
  })
135
136
  ```
136
137
 
@@ -214,26 +215,26 @@ module.exports = buildFastify
214
215
 
215
216
  **test.js**
216
217
  ```js
217
- const tap = require('tap')
218
+ const { test } = require('node:test')
218
219
  const buildFastify = require('./app')
219
220
 
220
- tap.test('GET `/` route', t => {
221
+ test('GET `/` route', t => {
221
222
  t.plan(4)
222
223
 
223
224
  const fastify = buildFastify()
224
225
 
225
226
  // At the end of your tests it is highly recommended to call `.close()`
226
227
  // to ensure that all connections to external services get closed.
227
- t.teardown(() => fastify.close())
228
+ t.after(() => fastify.close())
228
229
 
229
230
  fastify.inject({
230
231
  method: 'GET',
231
232
  url: '/'
232
233
  }, (err, response) => {
233
- t.error(err)
234
- t.equal(response.statusCode, 200)
235
- t.equal(response.headers['content-type'], 'application/json; charset=utf-8')
236
- t.same(response.json(), { hello: 'world' })
234
+ t.assert.ifError(err)
235
+ t.assert.strictEqual(response.statusCode, 200)
236
+ t.assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
237
+ t.assert.deepStrictEqual(response.json(), { hello: 'world' })
237
238
  })
238
239
  })
239
240
  ```
@@ -248,11 +249,11 @@ Uses **app.js** from the previous example.
248
249
 
249
250
  **test-listen.js** (testing with [`undici`](https://www.npmjs.com/package/undici))
250
251
  ```js
251
- const tap = require('tap')
252
+ const { test } = require('node:test')
252
253
  const { Client } = require('undici')
253
254
  const buildFastify = require('./app')
254
255
 
255
- tap.test('should work with undici', async t => {
256
+ test('should work with undici', async t => {
256
257
  t.plan(2)
257
258
 
258
259
  const fastify = buildFastify()
@@ -263,63 +264,64 @@ tap.test('should work with undici', async t => {
263
264
  'http://localhost:' + fastify.server.address().port, {
264
265
  keepAliveTimeout: 10,
265
266
  keepAliveMaxTimeout: 10
266
- }
267
+ }
267
268
  )
268
269
 
269
- t.teardown(() => {
270
+ t.after(() => {
270
271
  fastify.close()
271
272
  client.close()
272
273
  })
273
274
 
274
275
  const response = await client.request({ method: 'GET', path: '/' })
275
276
 
276
- t.equal(await response.body.text(), '{"hello":"world"}')
277
- t.equal(response.statusCode, 200)
277
+ t.assert.strictEqual(await response.body.text(), '{"hello":"world"}')
278
+ t.assert.strictEqual(response.statusCode, 200)
278
279
  })
279
280
  ```
280
281
 
281
- Alternatively, starting with Node.js 18,
282
- [`fetch`](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch)
282
+ Alternatively, starting with Node.js 18,
283
+ [`fetch`](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch)
283
284
  may be used without requiring any extra dependencies:
284
285
 
285
286
  **test-listen.js**
286
287
  ```js
287
- const tap = require('tap')
288
+ const { test } = require('node:test')
288
289
  const buildFastify = require('./app')
289
290
 
290
- tap.test('should work with fetch', async t => {
291
+ test('should work with fetch', async t => {
291
292
  t.plan(3)
292
293
 
293
294
  const fastify = buildFastify()
294
295
 
295
- t.teardown(() => fastify.close())
296
+ t.after(() => fastify.close())
296
297
 
297
298
  await fastify.listen()
298
-
299
+
299
300
  const response = await fetch(
300
301
  'http://localhost:' + fastify.server.address().port
301
302
  )
302
303
 
303
- t.equal(response.status, 200)
304
- t.equal(
304
+ t.assert.strictEqual(response.status, 200)
305
+ t.assert.strictEqual(
305
306
  response.headers.get('content-type'),
306
307
  'application/json; charset=utf-8'
307
308
  )
308
- t.has(await response.json(), { hello: 'world' })
309
+ const jsonResult = await response.json()
310
+ t.assert.strictEqual(jsonResult.hello, 'world')
309
311
  })
310
312
  ```
311
313
 
312
314
  **test-ready.js** (testing with
313
315
  [`SuperTest`](https://www.npmjs.com/package/supertest))
314
316
  ```js
315
- const tap = require('tap')
317
+ const { test } = require('node:test')
316
318
  const supertest = require('supertest')
317
319
  const buildFastify = require('./app')
318
320
 
319
- tap.test('GET `/` route', async (t) => {
321
+ test('GET `/` route', async (t) => {
320
322
  const fastify = buildFastify()
321
323
 
322
- t.teardown(() => fastify.close())
324
+ t.after(() => fastify.close())
323
325
 
324
326
  await fastify.ready()
325
327
 
@@ -327,21 +329,20 @@ tap.test('GET `/` route', async (t) => {
327
329
  .get('/')
328
330
  .expect(200)
329
331
  .expect('Content-Type', 'application/json; charset=utf-8')
330
- t.same(response.body, { hello: 'world' })
332
+ t.assert.deepStrictEqual(response.body, { hello: 'world' })
331
333
  })
332
334
  ```
333
335
 
334
- ### How to inspect tap tests
336
+ ### How to inspect node tests
335
337
  1. Isolate your test by passing the `{only: true}` option
336
338
  ```javascript
337
339
  test('should ...', {only: true}, t => ...)
338
340
  ```
339
- 2. Run `tap` using `npx`
341
+ 2. Run `node --test`
340
342
  ```bash
341
- > npx tap -O -T --node-arg=--inspect-brk test/<test-file.test.js>
343
+ > node --test --test-only --node-arg=--inspect-brk test/<test-file.test.js>
342
344
  ```
343
- - `-O` specifies to run tests with the `only` option enabled
344
- - `-T` specifies not to timeout (while you're debugging)
345
+ - `--test-only` specifies to run tests with the `only` option enabled
345
346
  - `--node-arg=--inspect-brk` will launch the node debugger
346
347
  3. In VS Code, create and launch a `Node.js: Attach` debug configuration. No
347
348
  modification should be necessary.
@@ -355,7 +356,7 @@ Now you should be able to step through your test file (and the rest of
355
356
  Let's `cd` into a fresh directory called 'testing-plugin-example' and type `npm init
356
357
  -y` in our terminal.
357
358
 
358
- Run `npm i fastify fastify-plugin && npm i tap -D`
359
+ Run `npm i fastify fastify-plugin`
359
360
 
360
361
  **plugin/myFirstPlugin.js**:
361
362
 
@@ -376,16 +377,16 @@ A basic example of a Plugin. See [Plugin Guide](./Plugins-Guide.md)
376
377
 
377
378
  ```js
378
379
  const Fastify = require("fastify");
379
- const tap = require("tap");
380
+ const { test } = require("node:test");
380
381
  const myPlugin = require("../plugin/myFirstPlugin");
381
382
 
382
- tap.test("Test the Plugin Route", async t => {
383
+ test("Test the Plugin Route", async t => {
383
384
  // Create a mock fastify application to test the plugin
384
385
  const fastify = Fastify()
385
386
 
386
387
  fastify.register(myPlugin)
387
388
 
388
- // Add an endpoint of your choice
389
+ // Add an endpoint of your choice
389
390
  fastify.get("/", async (request, reply) => {
390
391
  return ({ message: request.helloRequest })
391
392
  })
@@ -395,7 +396,7 @@ tap.test("Test the Plugin Route", async t => {
395
396
  method: "GET",
396
397
  url: "/"
397
398
  })
398
-
399
+
399
400
  console.log('status code: ', fastifyResponse.statusCode)
400
401
  console.log('body: ', fastifyResponse.body)
401
402
  })
@@ -412,18 +413,18 @@ Now we can replace our `console.log` calls with actual tests!
412
413
 
413
414
  In your `package.json` change the "test" script to:
414
415
 
415
- `"test": "tap --reporter=list --watch"`
416
+ `"test": "node --test --watch"`
416
417
 
417
- Create the tap test for the endpoint.
418
+ Create the test for the endpoint.
418
419
 
419
420
  **test/myFirstPlugin.test.js**:
420
421
 
421
422
  ```js
422
423
  const Fastify = require("fastify");
423
- const tap = require("tap");
424
+ const { test } = require("node:test");
424
425
  const myPlugin = require("../plugin/myFirstPlugin");
425
426
 
426
- tap.test("Test the Plugin Route", async t => {
427
+ test("Test the Plugin Route", async t => {
427
428
  // Specifies the number of test
428
429
  t.plan(2)
429
430
 
@@ -439,9 +440,9 @@ tap.test("Test the Plugin Route", async t => {
439
440
  method: "GET",
440
441
  url: "/"
441
442
  })
442
-
443
- t.equal(fastifyResponse.statusCode, 200)
444
- t.same(JSON.parse(fastifyResponse.body), { message: "Hello World" })
443
+
444
+ t.assert.strictEqual(fastifyResponse.statusCode, 200)
445
+ t.assert.deepStrictEqual(JSON.parse(fastifyResponse.body), { message: "Hello World" })
445
446
  })
446
447
  ```
447
448
 
@@ -453,10 +454,10 @@ Test the ```.decorate()``` and ```.decorateRequest()```.
453
454
 
454
455
  ```js
455
456
  const Fastify = require("fastify");
456
- const tap = require("tap");
457
+ const { test }= require("node:test");
457
458
  const myPlugin = require("../plugin/myFirstPlugin");
458
459
 
459
- tap.test("Test the Plugin Route", async t => {
460
+ test("Test the Plugin Route", async t => {
460
461
  t.plan(5)
461
462
  const fastify = Fastify()
462
463
 
@@ -464,9 +465,9 @@ tap.test("Test the Plugin Route", async t => {
464
465
 
465
466
  fastify.get("/", async (request, reply) => {
466
467
  // Testing the fastify decorators
467
- t.not(request.helloRequest, null)
468
- t.ok(request.helloRequest, "Hello World")
469
- t.ok(fastify.helloInstance, "Hello Fastify Instance")
468
+ t.assert.ifError(request.helloRequest)
469
+ t.assert.ok(request.helloRequest, "Hello World")
470
+ t.assert.ok(fastify.helloInstance, "Hello Fastify Instance")
470
471
  return ({ message: request.helloRequest })
471
472
  })
472
473
 
@@ -474,7 +475,7 @@ tap.test("Test the Plugin Route", async t => {
474
475
  method: "GET",
475
476
  url: "/"
476
477
  })
477
- t.equal(fastifyResponse.statusCode, 200)
478
- t.same(JSON.parse(fastifyResponse.body), { message: "Hello World" })
478
+ t.assert.strictEqual(fastifyResponse.statusCode, 200)
479
+ t.assert.deepStrictEqual(JSON.parse(fastifyResponse.body), { message: "Hello World" })
479
480
  })
480
- ```
481
+ ```
@@ -60,10 +60,10 @@ A plugin without tests will not be accepted to the ecosystem list. A lack of
60
60
  tests does not inspire trust nor guarantee that the code will continue to work
61
61
  among different versions of its dependencies.
62
62
 
63
- We do not enforce any testing library. We use [`tap`](https://www.node-tap.org/)
63
+ We do not enforce any testing library. We use [`node:test`](https://nodejs.org/api/test.html)
64
64
  since it offers out-of-the-box parallel testing and code coverage, but it is up
65
65
  to you to choose your library of preference.
66
- We highly recommend you read the [Plugin Testing](./Testing.md#plugins) to
66
+ We highly recommend you read the [Plugin Testing](./Testing.md#plugins) to
67
67
  learn about how to test your plugins.
68
68
 
69
69
  ## Code Linter
@@ -10,9 +10,9 @@ Whereas exhaustive type narrowing checks normally rely on `never` to represent
10
10
  an unreachable state, reduction in type provider interfaces should only be done
11
11
  up to `unknown`.
12
12
 
13
- The reasoning is that certain methods of `FastifyInstance` are
14
- contravariant on `TypeProvider`, which can lead to TypeScript surfacing
15
- assignability issues unless the custom type provider interface is
13
+ The reasoning is that certain methods of `FastifyInstance` are
14
+ contravariant on `TypeProvider`, which can lead to TypeScript surfacing
15
+ assignability issues unless the custom type provider interface is
16
16
  substitutable with `FastifyTypeProviderDefault`.
17
17
 
18
18
  For example, `FastifyTypeProviderDefault` will not be assignable to the following:
@@ -53,7 +53,7 @@ fastify.addContentTypeParser(['text/xml', 'application/xml'], function (request,
53
53
 
54
54
  // Async is also supported in Node versions >= 8.0.0
55
55
  fastify.addContentTypeParser('application/jsoff', async function (request, payload) {
56
- var res = await jsoffParserAsync(payload)
56
+ const res = await jsoffParserAsync(payload)
57
57
 
58
58
  return res
59
59
  })
@@ -181,7 +181,7 @@ limit is exceeded the custom parser will not be invoked.
181
181
  ```js
182
182
  fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
183
183
  try {
184
- var json = JSON.parse(body)
184
+ const json = JSON.parse(body)
185
185
  done(null, json)
186
186
  } catch (err) {
187
187
  err.statusCode = 400
@@ -206,7 +206,7 @@ There are some cases where you need to catch all requests regardless of their
206
206
  content type. With Fastify, you can just use the `'*'` content type.
207
207
  ```js
208
208
  fastify.addContentTypeParser('*', function (request, payload, done) {
209
- var data = ''
209
+ let data = ''
210
210
  payload.on('data', chunk => { data += chunk })
211
211
  payload.on('end', () => {
212
212
  done(null, data)
@@ -266,7 +266,7 @@ only on those that don't have a specific one, you should call the
266
266
  fastify.removeAllContentTypeParsers()
267
267
 
268
268
  fastify.addContentTypeParser('*', function (request, payload, done) {
269
- var data = ''
269
+ const data = ''
270
270
  payload.on('data', chunk => { data += chunk })
271
271
  payload.on('end', () => {
272
272
  done(null, data)
@@ -59,7 +59,7 @@ close as possible to the value intended to be set dynamically in the future.
59
59
  Initialize a decorator as a `''` if the intended value is a string, and as
60
60
  `null` if it will be an object or a function.
61
61
 
62
- Remember this example works only with value types as reference types will
62
+ Remember this example works only with value types as reference types will
63
63
  thrown and error during the fastify startup. See [decorateRequest](#decorate-request).
64
64
 
65
65
  See [JavaScript engine fundamentals: Shapes and Inline
@@ -109,7 +109,7 @@ fastify.decorate('db', new DbConnection())
109
109
  fastify.get('/', async function (request, reply) {
110
110
  // using return
111
111
  return { hello: await this.db.query('world') }
112
-
112
+
113
113
  // or
114
114
  // using reply.send()
115
115
  reply.send({ hello: await this.db.query('world') })
@@ -5,7 +5,7 @@
5
5
 
6
6
  **Table of contents**
7
7
  - [Errors](#errors)
8
- - [Error Handling In Node.js](#error-handling-in-node.js)
8
+ - [Error Handling In Node.js](#error-handling-in-nodejs)
9
9
  - [Uncaught Errors](#uncaught-errors)
10
10
  - [Catching Errors In Promises](#catching-errors-in-promises)
11
11
  - [Errors In Fastify](#errors-in-fastify)
@@ -178,13 +178,13 @@ When utilizing Fastify's custom error handling through [`setErrorHandler`](./Ser
178
178
  you should be aware of how errors are propagated between custom and default
179
179
  error handlers.
180
180
 
181
- If a plugin's error handler re-throws an error, and the error is not an
181
+ If a plugin's error handler re-throws an error, and the error is not an
182
182
  instance of [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
183
183
  (as seen in the `/bad` route in the following example), it will not propagate
184
184
  to the parent context error handler. Instead, it will be caught by the default
185
185
  error handler.
186
186
 
187
- To ensure consistent error handling, it is recommended to throw instances of
187
+ To ensure consistent error handling, it is recommended to throw instances of
188
188
  `Error`. For instance, in the following example, replacing `throw 'foo'` with
189
189
  `throw new Error('foo')` in the `/bad` route ensures that errors propagate through
190
190
  the custom error handling chain as intended. This practice helps avoid potential
@@ -107,7 +107,7 @@ returned stream. This property is used to correctly match the request payload
107
107
  with the `Content-Length` header value. Ideally, this property should be updated
108
108
  on each received chunk.
109
109
 
110
- **Notice:** The size of the returned stream is checked to not exceed the limit
110
+ **Notice:** The size of the returned stream is checked to not exceed the limit
111
111
  set in [`bodyLimit`](./Server.md#bodylimit) option.
112
112
 
113
113
  ### preValidation
@@ -256,8 +256,8 @@ The `onResponse` hook is executed when a response has been sent, so you will not
256
256
  be able to send more data to the client. It can however be useful for sending
257
257
  data to external services, for example, to gather statistics.
258
258
 
259
- **Note:** setting `disableRequestLogging` to `true` will disable any error log
260
- inside the `onResponse` hook. In this case use `try - catch` to log errors.
259
+ **Note:** setting `disableRequestLogging` to `true` will disable any error log
260
+ inside the `onResponse` hook. In this case use `try - catch` to log errors.
261
261
 
262
262
  ### onTimeout
263
263
 
@@ -428,8 +428,8 @@ fastify.addHook('onReady', async function () {
428
428
 
429
429
  ### onListen
430
430
 
431
- Triggered when the server starts listening for requests. The hooks run one
432
- after another. If a hook function causes an error, it is logged and
431
+ Triggered when the server starts listening for requests. The hooks run one
432
+ after another. If a hook function causes an error, it is logged and
433
433
  ignored, allowing the queue of hooks to continue. Hook functions accept one
434
434
  argument: a callback, `done`, to be invoked after the hook function is
435
435
  complete. Hook functions are invoked with `this` bound to the associated
@@ -451,7 +451,7 @@ fastify.addHook('onListen', async function () {
451
451
  })
452
452
  ```
453
453
 
454
- > **Note**
454
+ > **Note**
455
455
  > This hook will not run when the server is started using `fastify.inject()` or `fastify.ready()`
456
456
 
457
457
  ### onClose
@@ -462,7 +462,7 @@ HTTP requests have been completed.
462
462
  It is useful when [plugins](./Plugins.md) need a "shutdown" event, for example,
463
463
  to close an open connection to a database.
464
464
 
465
- The hook function takes the Fastify instance as a first argument,
465
+ The hook function takes the Fastify instance as a first argument,
466
466
  and a `done` callback for synchronous hook functions.
467
467
  ```js
468
468
  // callback style
@@ -48,6 +48,12 @@ A "month" is defined as 30 consecutive days.
48
48
  > dependency as `"fastify": "~3.15.x"`. This will leave your application
49
49
  > vulnerable, so please use with caution.
50
50
 
51
+ ### Security Support Beyond LTS
52
+
53
+ Fastify's partner, HeroDevs, provides commercial security support through the
54
+ OpenJS Ecosystem Sustainability Program for versions of Fastify that are EOL.
55
+ For more information, see their [Never Ending Support][hd-link] service.
56
+
51
57
  ### Schedule
52
58
 
53
59
  `<a id="lts-schedule"></a>`
@@ -81,3 +87,5 @@ Using [yarn](https://yarnpkg.com/) might require passing the `--ignore-engines`
81
87
  flag.
82
88
 
83
89
  [semver]: https://semver.org/
90
+
91
+ [hd-link]: https://www.herodevs.com/support/fastify-nes?utm_source=fastify&utm_medium=link&utm_campaign=eol_support_fastify
@@ -204,15 +204,16 @@ on serializers for more information.
204
204
  *Any logger other than Pino will ignore this option.*
205
205
 
206
206
  You can also supply your own logger instance. Instead of passing configuration
207
- options, pass the instance. The logger you supply must conform to the Pino
208
- interface; that is, it must have the following methods: `info`, `error`,
209
- `debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a string property `level`.
207
+ options, pass the instance as `loggerInstance`. The logger you supply must
208
+ conform to the Pino interface; that is, it must have the following methods:
209
+ `info`, `error`, `debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a
210
+ string property `level`.
210
211
 
211
212
  Example:
212
213
 
213
214
  ```js
214
215
  const log = require('pino')({ level: 'info' })
215
- const fastify = require('fastify')({ logger: log })
216
+ const fastify = require('fastify')({ loggerInstance: log })
216
217
 
217
218
  log.info('does not have request information')
218
219