fastify 5.0.0 → 5.1.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 (138) hide show
  1. package/.borp.yaml +3 -0
  2. package/.vscode/settings.json +22 -0
  3. package/docs/Guides/Ecosystem.md +1 -8
  4. package/docs/Guides/Migration-Guide-V5.md +128 -4
  5. package/docs/Guides/Testing.md +51 -50
  6. package/docs/Guides/Write-Plugin.md +1 -1
  7. package/docs/Reference/ContentTypeParser.md +4 -4
  8. package/docs/Reference/Errors.md +1 -1
  9. package/docs/Reference/Reply.md +1 -5
  10. package/docs/Reference/Request.md +2 -1
  11. package/docs/Reference/Routes.md +9 -6
  12. package/docs/Reference/Server.md +1 -1
  13. package/fastify.d.ts +10 -1
  14. package/fastify.js +8 -6
  15. package/lib/contentTypeParser.js +9 -7
  16. package/lib/context.js +1 -2
  17. package/lib/fourOhFour.js +1 -1
  18. package/lib/{logger.js → logger-factory.js} +70 -122
  19. package/lib/logger-pino.js +68 -0
  20. package/lib/pluginOverride.js +1 -1
  21. package/lib/pluginUtils.js +2 -2
  22. package/lib/reply.js +4 -5
  23. package/lib/request.js +15 -9
  24. package/lib/route.js +23 -22
  25. package/lib/validation.js +2 -2
  26. package/package.json +12 -13
  27. package/test/404s.test.js +675 -629
  28. package/test/500s.test.js +72 -63
  29. package/test/allowUnsafeRegex.test.js +30 -26
  30. package/test/als.test.js +48 -45
  31. package/test/async-await.test.js +148 -134
  32. package/test/async-dispose.test.js +4 -4
  33. package/test/async_hooks.test.js +30 -28
  34. package/test/{bodyLimit.test.js → body-limit.test.js} +61 -58
  35. package/test/buffer.test.js +9 -10
  36. package/test/build/error-serializer.test.js +3 -4
  37. package/test/build/version.test.js +2 -3
  38. package/test/bundler/esbuild/bundler-test.js +10 -9
  39. package/test/bundler/webpack/bundler-test.js +10 -9
  40. package/test/case-insensitive.test.js +31 -28
  41. package/test/chainable.test.js +4 -5
  42. package/test/check.test.js +8 -9
  43. package/test/childLoggerFactory.test.js +56 -19
  44. package/test/client-timeout.test.js +5 -5
  45. package/test/close-pipelining.test.js +6 -7
  46. package/test/conditional-pino.test.js +47 -0
  47. package/test/connectionTimeout.test.js +10 -11
  48. package/test/constrained-routes.test.js +243 -236
  49. package/test/content-parser.test.js +17 -0
  50. package/test/custom-http-server.test.js +16 -20
  51. package/test/diagnostics-channel/404.test.js +15 -15
  52. package/test/diagnostics-channel/async-delay-request.test.js +25 -25
  53. package/test/diagnostics-channel/async-request.test.js +24 -24
  54. package/test/diagnostics-channel/error-before-handler.test.js +4 -5
  55. package/test/diagnostics-channel/error-request.test.js +19 -19
  56. package/test/diagnostics-channel/error-status.test.js +8 -8
  57. package/test/diagnostics-channel/init.test.js +6 -7
  58. package/test/diagnostics-channel/sync-delay-request.test.js +16 -16
  59. package/test/diagnostics-channel/sync-request-reply.test.js +16 -16
  60. package/test/diagnostics-channel/sync-request.test.js +19 -19
  61. package/test/esm/errorCodes.test.mjs +5 -5
  62. package/test/esm/esm.test.mjs +3 -3
  63. package/test/esm/named-exports.mjs +3 -3
  64. package/test/esm/other.mjs +2 -2
  65. package/test/hooks.test.js +6 -6
  66. package/test/http-methods/copy.test.js +22 -24
  67. package/test/http-methods/custom-http-methods.test.js +24 -21
  68. package/test/http-methods/get.test.js +97 -84
  69. package/test/http-methods/head.test.js +63 -54
  70. package/test/http-methods/lock.test.js +21 -20
  71. package/test/http-methods/mkcalendar.test.js +31 -27
  72. package/test/http-methods/mkcol.test.js +10 -10
  73. package/test/http-methods/move.test.js +11 -11
  74. package/test/http-methods/propfind.test.js +32 -27
  75. package/test/http-methods/proppatch.test.js +21 -19
  76. package/test/http-methods/report.test.js +32 -27
  77. package/test/http-methods/search.test.js +52 -47
  78. package/test/http-methods/trace.test.js +3 -4
  79. package/test/http-methods/unlock.test.js +10 -10
  80. package/test/http2/closing.test.js +50 -58
  81. package/test/http2/constraint.test.js +47 -50
  82. package/test/http2/head.test.js +18 -19
  83. package/test/http2/missing-http2-module.test.js +4 -5
  84. package/test/http2/plain.test.js +31 -31
  85. package/test/http2/secure-with-fallback.test.js +61 -61
  86. package/test/http2/secure.test.js +28 -31
  87. package/test/http2/unknown-http-method.test.js +13 -14
  88. package/test/https/custom-https-server.test.js +6 -7
  89. package/test/https/https.test.js +78 -78
  90. package/test/imports.test.js +5 -6
  91. package/test/internals/all.test.js +8 -11
  92. package/test/internals/contentTypeParser.test.js +5 -6
  93. package/test/internals/context.test.js +9 -11
  94. package/test/internals/decorator.test.js +20 -21
  95. package/test/internals/errors.test.js +427 -427
  96. package/test/internals/handleRequest.test.js +53 -42
  97. package/test/internals/hookRunner.test.js +99 -100
  98. package/test/internals/hooks.test.js +31 -35
  99. package/test/internals/initialConfig.test.js +92 -80
  100. package/test/internals/logger.test.js +28 -28
  101. package/test/internals/plugin.test.js +17 -18
  102. package/test/internals/reply-serialize.test.js +106 -106
  103. package/test/internals/reply.test.js +620 -585
  104. package/test/internals/reqIdGenFactory.test.js +31 -31
  105. package/test/internals/request-validate.test.js +218 -221
  106. package/test/internals/request.test.js +225 -107
  107. package/test/internals/server.test.js +15 -12
  108. package/test/internals/validation.test.js +35 -36
  109. package/test/{keepAliveTimeout.test.js → keep-alive-timeout.test.js} +9 -10
  110. package/test/noop-set.test.js +5 -5
  111. package/test/request-error.test.js +122 -0
  112. package/test/request-header-host.test.js +197 -0
  113. package/test/route.1.test.js +79 -72
  114. package/test/route.2.test.js +17 -16
  115. package/test/route.3.test.js +30 -26
  116. package/test/route.4.test.js +21 -25
  117. package/test/route.5.test.js +45 -64
  118. package/test/route.6.test.js +70 -89
  119. package/test/route.7.test.js +61 -65
  120. package/test/route.8.test.js +62 -0
  121. package/test/same-shape.test.js +5 -5
  122. package/test/serialize-response.test.js +9 -10
  123. package/test/server.test.js +67 -70
  124. package/test/test-reporter.mjs +68 -0
  125. package/test/types/fastify.test-d.ts +12 -0
  126. package/test/types/hooks.test-d.ts +2 -1
  127. package/test/types/instance.test-d.ts +10 -12
  128. package/test/types/plugin.test-d.ts +15 -7
  129. package/test/types/register.test-d.ts +20 -4
  130. package/test/types/route.test-d.ts +33 -3
  131. package/test/versioned-routes.test.js +126 -113
  132. package/test/web-api.test.js +48 -37
  133. package/test/wrapThenable.test.js +10 -9
  134. package/types/hooks.d.ts +1 -0
  135. package/types/register.d.ts +12 -3
  136. package/types/request.d.ts +2 -2
  137. package/types/utils.d.ts +10 -2
  138. package/test/types/import.js +0 -2
@@ -1,54 +1,50 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
5
-
3
+ const { test } = require('node:test')
6
4
  const { Hooks } = require('../../lib/hooks')
7
5
  const noop = () => {}
8
6
 
9
7
  test('hooks should have 4 array with the registered hooks', t => {
10
8
  const hooks = new Hooks()
11
- t.equal(typeof hooks, 'object')
12
- t.ok(Array.isArray(hooks.onRequest))
13
- t.ok(Array.isArray(hooks.onSend))
14
- t.ok(Array.isArray(hooks.preParsing))
15
- t.ok(Array.isArray(hooks.preValidation))
16
- t.ok(Array.isArray(hooks.preHandler))
17
- t.ok(Array.isArray(hooks.onResponse))
18
- t.ok(Array.isArray(hooks.onError))
19
- t.end()
9
+ t.assert.strictEqual(typeof hooks, 'object')
10
+ t.assert.ok(Array.isArray(hooks.onRequest))
11
+ t.assert.ok(Array.isArray(hooks.onSend))
12
+ t.assert.ok(Array.isArray(hooks.preParsing))
13
+ t.assert.ok(Array.isArray(hooks.preValidation))
14
+ t.assert.ok(Array.isArray(hooks.preHandler))
15
+ t.assert.ok(Array.isArray(hooks.onResponse))
16
+ t.assert.ok(Array.isArray(hooks.onError))
20
17
  })
21
18
 
22
19
  test('hooks.add should add a hook to the given hook', t => {
23
20
  const hooks = new Hooks()
24
21
  hooks.add('onRequest', noop)
25
- t.equal(hooks.onRequest.length, 1)
26
- t.equal(typeof hooks.onRequest[0], 'function')
22
+ t.assert.strictEqual(hooks.onRequest.length, 1)
23
+ t.assert.strictEqual(typeof hooks.onRequest[0], 'function')
27
24
 
28
25
  hooks.add('preParsing', noop)
29
- t.equal(hooks.preParsing.length, 1)
30
- t.equal(typeof hooks.preParsing[0], 'function')
26
+ t.assert.strictEqual(hooks.preParsing.length, 1)
27
+ t.assert.strictEqual(typeof hooks.preParsing[0], 'function')
31
28
 
32
29
  hooks.add('preValidation', noop)
33
- t.equal(hooks.preValidation.length, 1)
34
- t.equal(typeof hooks.preValidation[0], 'function')
30
+ t.assert.strictEqual(hooks.preValidation.length, 1)
31
+ t.assert.strictEqual(typeof hooks.preValidation[0], 'function')
35
32
 
36
33
  hooks.add('preHandler', noop)
37
- t.equal(hooks.preHandler.length, 1)
38
- t.equal(typeof hooks.preHandler[0], 'function')
34
+ t.assert.strictEqual(hooks.preHandler.length, 1)
35
+ t.assert.strictEqual(typeof hooks.preHandler[0], 'function')
39
36
 
40
37
  hooks.add('onResponse', noop)
41
- t.equal(hooks.onResponse.length, 1)
42
- t.equal(typeof hooks.onResponse[0], 'function')
38
+ t.assert.strictEqual(hooks.onResponse.length, 1)
39
+ t.assert.strictEqual(typeof hooks.onResponse[0], 'function')
43
40
 
44
41
  hooks.add('onSend', noop)
45
- t.equal(hooks.onSend.length, 1)
46
- t.equal(typeof hooks.onSend[0], 'function')
42
+ t.assert.strictEqual(hooks.onSend.length, 1)
43
+ t.assert.strictEqual(typeof hooks.onSend[0], 'function')
47
44
 
48
45
  hooks.add('onError', noop)
49
- t.equal(hooks.onError.length, 1)
50
- t.equal(typeof hooks.onError[0], 'function')
51
- t.end()
46
+ t.assert.strictEqual(hooks.onError.length, 1)
47
+ t.assert.strictEqual(typeof hooks.onError[0], 'function')
52
48
  })
53
49
 
54
50
  test('hooks should throw on unexisting handler', t => {
@@ -56,9 +52,9 @@ test('hooks should throw on unexisting handler', t => {
56
52
  const hooks = new Hooks()
57
53
  try {
58
54
  hooks.add('onUnexistingHook', noop)
59
- t.fail()
55
+ t.assert.fail()
60
56
  } catch (e) {
61
- t.pass()
57
+ t.assert.ok(true)
62
58
  }
63
59
  })
64
60
 
@@ -67,17 +63,17 @@ test('should throw on wrong parameters', t => {
67
63
  t.plan(4)
68
64
  try {
69
65
  hooks.add(null, () => {})
70
- t.fail()
66
+ t.assert.fail()
71
67
  } catch (e) {
72
- t.equal(e.code, 'FST_ERR_HOOK_INVALID_TYPE')
73
- t.equal(e.message, 'The hook name must be a string')
68
+ t.assert.strictEqual(e.code, 'FST_ERR_HOOK_INVALID_TYPE')
69
+ t.assert.strictEqual(e.message, 'The hook name must be a string')
74
70
  }
75
71
 
76
72
  try {
77
73
  hooks.add('onSend', null)
78
- t.fail()
74
+ t.assert.fail()
79
75
  } catch (e) {
80
- t.equal(e.code, 'FST_ERR_HOOK_INVALID_HANDLER')
81
- t.equal(e.message, 'onSend hook should be a function, instead got [object Null]')
76
+ t.assert.strictEqual(e.code, 'FST_ERR_HOOK_INVALID_HANDLER')
77
+ t.assert.strictEqual(e.message, 'onSend hook should be a function, instead got [object Null]')
82
78
  }
83
79
  })
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { test, before } = require('tap')
3
+ const { test, before } = require('node:test')
4
4
  const Fastify = require('../..')
5
5
  const helper = require('../helper')
6
6
  const http = require('node:http')
@@ -23,7 +23,7 @@ before(async function () {
23
23
 
24
24
  test('Fastify.initialConfig is an object', t => {
25
25
  t.plan(1)
26
- t.type(Fastify().initialConfig, 'object')
26
+ t.assert.ok(typeof Fastify().initialConfig === 'object')
27
27
  })
28
28
 
29
29
  test('without options passed to Fastify, initialConfig should expose default values', t => {
@@ -51,7 +51,7 @@ test('without options passed to Fastify, initialConfig should expose default val
51
51
  useSemicolonDelimiter: false
52
52
  }
53
53
 
54
- t.same(Fastify().initialConfig, fastifyDefaultOptions)
54
+ t.assert.deepStrictEqual(Fastify().initialConfig, fastifyDefaultOptions)
55
55
  })
56
56
 
57
57
  test('Fastify.initialConfig should expose all options', t => {
@@ -114,30 +114,30 @@ test('Fastify.initialConfig should expose all options', t => {
114
114
  }
115
115
 
116
116
  const fastify = Fastify(options)
117
- t.equal(fastify.initialConfig.http2, true)
118
- t.equal(fastify.initialConfig.https, true, 'for security reason the key cert is hidden')
119
- t.equal(fastify.initialConfig.ignoreTrailingSlash, true)
120
- t.equal(fastify.initialConfig.ignoreDuplicateSlashes, true)
121
- t.equal(fastify.initialConfig.maxParamLength, 200)
122
- t.equal(fastify.initialConfig.connectionTimeout, 0)
123
- t.equal(fastify.initialConfig.keepAliveTimeout, 72000)
124
- t.equal(fastify.initialConfig.bodyLimit, 1049600)
125
- t.equal(fastify.initialConfig.onProtoPoisoning, 'remove')
126
- t.equal(fastify.initialConfig.caseSensitive, true)
127
- t.equal(fastify.initialConfig.useSemicolonDelimiter, false)
128
- t.equal(fastify.initialConfig.allowUnsafeRegex, false)
129
- t.equal(fastify.initialConfig.requestIdHeader, 'request-id-alt')
130
- t.equal(fastify.initialConfig.pluginTimeout, 20000)
131
- t.ok(fastify.initialConfig.constraints.version)
117
+ t.assert.strictEqual(fastify.initialConfig.http2, true)
118
+ t.assert.strictEqual(fastify.initialConfig.https, true, 'for security reason the key cert is hidden')
119
+ t.assert.strictEqual(fastify.initialConfig.ignoreTrailingSlash, true)
120
+ t.assert.strictEqual(fastify.initialConfig.ignoreDuplicateSlashes, true)
121
+ t.assert.strictEqual(fastify.initialConfig.maxParamLength, 200)
122
+ t.assert.strictEqual(fastify.initialConfig.connectionTimeout, 0)
123
+ t.assert.strictEqual(fastify.initialConfig.keepAliveTimeout, 72000)
124
+ t.assert.strictEqual(fastify.initialConfig.bodyLimit, 1049600)
125
+ t.assert.strictEqual(fastify.initialConfig.onProtoPoisoning, 'remove')
126
+ t.assert.strictEqual(fastify.initialConfig.caseSensitive, true)
127
+ t.assert.strictEqual(fastify.initialConfig.useSemicolonDelimiter, false)
128
+ t.assert.strictEqual(fastify.initialConfig.allowUnsafeRegex, false)
129
+ t.assert.strictEqual(fastify.initialConfig.requestIdHeader, 'request-id-alt')
130
+ t.assert.strictEqual(fastify.initialConfig.pluginTimeout, 20000)
131
+ t.assert.ok(fastify.initialConfig.constraints.version)
132
132
 
133
133
  // obfuscated options:
134
- t.equal(fastify.initialConfig.serverFactory, undefined)
135
- t.equal(fastify.initialConfig.trustProxy, undefined)
136
- t.equal(fastify.initialConfig.genReqId, undefined)
137
- t.equal(fastify.initialConfig.childLoggerFactory, undefined)
138
- t.equal(fastify.initialConfig.querystringParser, undefined)
139
- t.equal(fastify.initialConfig.logger, undefined)
140
- t.equal(fastify.initialConfig.trustProxy, undefined)
134
+ t.assert.strictEqual(fastify.initialConfig.serverFactory, undefined)
135
+ t.assert.strictEqual(fastify.initialConfig.trustProxy, undefined)
136
+ t.assert.strictEqual(fastify.initialConfig.genReqId, undefined)
137
+ t.assert.strictEqual(fastify.initialConfig.childLoggerFactory, undefined)
138
+ t.assert.strictEqual(fastify.initialConfig.querystringParser, undefined)
139
+ t.assert.strictEqual(fastify.initialConfig.logger, undefined)
140
+ t.assert.strictEqual(fastify.initialConfig.trustProxy, undefined)
141
141
  })
142
142
 
143
143
  test('Should throw if you try to modify Fastify.initialConfig', t => {
@@ -146,12 +146,12 @@ test('Should throw if you try to modify Fastify.initialConfig', t => {
146
146
  const fastify = Fastify({ ignoreTrailingSlash: true })
147
147
  try {
148
148
  fastify.initialConfig.ignoreTrailingSlash = false
149
- t.fail()
149
+ t.assert.fail()
150
150
  } catch (error) {
151
- t.type(error, TypeError)
152
- t.equal(error.message, "Cannot assign to read only property 'ignoreTrailingSlash' of object '#<Object>'")
153
- t.ok(error.stack)
154
- t.pass()
151
+ t.assert.ok(error instanceof TypeError)
152
+ t.assert.strictEqual(error.message, "Cannot assign to read only property 'ignoreTrailingSlash' of object '#<Object>'")
153
+ t.assert.ok(error.stack)
154
+ t.assert.ok(true)
155
155
  }
156
156
  })
157
157
 
@@ -168,12 +168,12 @@ test('We must avoid shallow freezing and ensure that the whole object is freezed
168
168
 
169
169
  try {
170
170
  fastify.initialConfig.https.allowHTTP1 = false
171
- t.fail()
171
+ t.assert.fail()
172
172
  } catch (error) {
173
- t.type(error, TypeError)
174
- t.equal(error.message, "Cannot assign to read only property 'allowHTTP1' of object '#<Object>'")
175
- t.ok(error.stack)
176
- t.same(fastify.initialConfig.https, {
173
+ t.assert.ok(error instanceof TypeError)
174
+ t.assert.strictEqual(error.message, "Cannot assign to read only property 'allowHTTP1' of object '#<Object>'")
175
+ t.assert.ok(error.stack)
176
+ t.assert.deepStrictEqual(fastify.initialConfig.https, {
177
177
  allowHTTP1: true
178
178
  }, 'key cert removed')
179
179
  }
@@ -183,7 +183,7 @@ test('https value check', t => {
183
183
  t.plan(1)
184
184
 
185
185
  const fastify = Fastify({})
186
- t.notOk(fastify.initialConfig.https)
186
+ t.assert.ok(!fastify.initialConfig.https)
187
187
  })
188
188
 
189
189
  test('Return an error if options do not match the validation schema', t => {
@@ -192,14 +192,14 @@ test('Return an error if options do not match the validation schema', t => {
192
192
  try {
193
193
  Fastify({ ignoreTrailingSlash: 'string instead of boolean' })
194
194
 
195
- t.fail()
195
+ t.assert.fail()
196
196
  } catch (error) {
197
- t.type(error, Error)
198
- t.equal(error.name, 'FastifyError')
199
- t.equal(error.message, 'Invalid initialization options: \'["must be boolean"]\'')
200
- t.equal(error.code, 'FST_ERR_INIT_OPTS_INVALID')
201
- t.ok(error.stack)
202
- t.pass()
197
+ t.assert.ok(error instanceof Error)
198
+ t.assert.strictEqual(error.name, 'FastifyError')
199
+ t.assert.strictEqual(error.message, 'Invalid initialization options: \'["must be boolean"]\'')
200
+ t.assert.strictEqual(error.code, 'FST_ERR_INIT_OPTS_INVALID')
201
+ t.assert.ok(error.stack)
202
+ t.assert.ok(true)
203
203
  }
204
204
  })
205
205
 
@@ -216,10 +216,10 @@ test('Original options must not be frozen', t => {
216
216
 
217
217
  const fastify = Fastify(originalOptions)
218
218
 
219
- t.equal(Object.isFrozen(originalOptions), false)
220
- t.equal(Object.isFrozen(originalOptions.https), false)
221
- t.equal(Object.isFrozen(fastify.initialConfig), true)
222
- t.equal(Object.isFrozen(fastify.initialConfig.https), true)
219
+ t.assert.strictEqual(Object.isFrozen(originalOptions), false)
220
+ t.assert.strictEqual(Object.isFrozen(originalOptions.https), false)
221
+ t.assert.strictEqual(Object.isFrozen(fastify.initialConfig), true)
222
+ t.assert.strictEqual(Object.isFrozen(fastify.initialConfig.https), true)
223
223
  })
224
224
 
225
225
  test('Original options must not be altered (test deep cloning)', t => {
@@ -238,14 +238,14 @@ test('Original options must not be altered (test deep cloning)', t => {
238
238
  const fastify = Fastify(originalOptions)
239
239
 
240
240
  // initialConfig has been triggered
241
- t.equal(Object.isFrozen(fastify.initialConfig), true)
241
+ t.assert.strictEqual(Object.isFrozen(fastify.initialConfig), true)
242
242
 
243
243
  // originalOptions must not have been altered
244
- t.same(originalOptions.https.key, originalOptionsClone.https.key)
245
- t.same(originalOptions.https.cert, originalOptionsClone.https.cert)
244
+ t.assert.deepStrictEqual(originalOptions.https.key, originalOptionsClone.https.key)
245
+ t.assert.deepStrictEqual(originalOptions.https.cert, originalOptionsClone.https.cert)
246
246
  })
247
247
 
248
- test('Should not have issues when passing stream options to Pino.js', t => {
248
+ test('Should not have issues when passing stream options to Pino.js', (t, done) => {
249
249
  t.plan(17)
250
250
 
251
251
  const stream = split(JSON.parse)
@@ -267,8 +267,8 @@ test('Should not have issues when passing stream options to Pino.js', t => {
267
267
  return logger.child(bindings, opts)
268
268
  })
269
269
 
270
- t.type(fastify, 'object')
271
- t.same(fastify.initialConfig, {
270
+ t.assert.ok(typeof fastify === 'object')
271
+ t.assert.deepStrictEqual(fastify.initialConfig, {
272
272
  connectionTimeout: 0,
273
273
  keepAliveTimeout: 72000,
274
274
  maxRequestsPerSocket: 0,
@@ -290,42 +290,44 @@ test('Should not have issues when passing stream options to Pino.js', t => {
290
290
  useSemicolonDelimiter: false
291
291
  })
292
292
  } catch (error) {
293
- t.fail()
293
+ t.assert.fail()
294
294
  }
295
295
 
296
296
  fastify.get('/', function (req, reply) {
297
- t.ok(req.log)
297
+ t.assert.ok(req.log)
298
298
  reply.send({ hello: 'world' })
299
299
  })
300
300
 
301
301
  stream.once('data', listenAtLogLine => {
302
- t.ok(listenAtLogLine, 'listen at log message is ok')
302
+ t.assert.ok(listenAtLogLine, 'listen at log message is ok')
303
303
 
304
304
  stream.once('data', line => {
305
305
  const id = line.reqId
306
- t.ok(line.reqId, 'reqId is defined')
307
- t.equal(line.someBinding, 'value', 'child logger binding is set')
308
- t.ok(line.req, 'req is defined')
309
- t.equal(line.msg, 'incoming request', 'message is set')
310
- t.equal(line.req.method, 'GET', 'method is get')
306
+ t.assert.ok(line.reqId, 'reqId is defined')
307
+ t.assert.strictEqual(line.someBinding, 'value', 'child logger binding is set')
308
+ t.assert.ok(line.req, 'req is defined')
309
+ t.assert.strictEqual(line.msg, 'incoming request', 'message is set')
310
+ t.assert.strictEqual(line.req.method, 'GET', 'method is get')
311
311
 
312
312
  stream.once('data', line => {
313
- t.equal(line.reqId, id)
314
- t.ok(line.reqId, 'reqId is defined')
315
- t.equal(line.someBinding, 'value', 'child logger binding is set')
316
- t.ok(line.res, 'res is defined')
317
- t.equal(line.msg, 'request completed', 'message is set')
318
- t.equal(line.res.statusCode, 200, 'statusCode is 200')
319
- t.ok(line.responseTime, 'responseTime is defined')
313
+ t.assert.strictEqual(line.reqId, id)
314
+ t.assert.ok(line.reqId, 'reqId is defined')
315
+ t.assert.strictEqual(line.someBinding, 'value', 'child logger binding is set')
316
+ t.assert.ok(line.res, 'res is defined')
317
+ t.assert.strictEqual(line.msg, 'request completed', 'message is set')
318
+ t.assert.strictEqual(line.res.statusCode, 200, 'statusCode is 200')
319
+ t.assert.ok(line.responseTime, 'responseTime is defined')
320
320
  })
321
321
  })
322
322
  })
323
323
 
324
324
  fastify.listen({ port: 0, host: localhost }, err => {
325
- t.error(err)
326
- t.teardown(() => { fastify.close() })
325
+ t.assert.ifError(err)
326
+ t.after(() => { fastify.close() })
327
327
 
328
- http.get(`http://${localhostForURL}:${fastify.server.address().port}`)
328
+ http.get(`http://${localhostForURL}:${fastify.server.address().port}`, () => {
329
+ done()
330
+ })
329
331
  })
330
332
  })
331
333
 
@@ -348,22 +350,32 @@ test('deepFreezeObject() should not throw on TypedArray', t => {
348
350
  const frozenObject = deepFreezeObject(object)
349
351
 
350
352
  // Buffers should not be frozen, as they are Uint8Array inherited instances
351
- t.equal(Object.isFrozen(frozenObject.buffer), false)
353
+ t.assert.strictEqual(Object.isFrozen(frozenObject.buffer), false)
352
354
 
353
- t.equal(Object.isFrozen(frozenObject), true)
354
- t.equal(Object.isFrozen(frozenObject.object), true)
355
- t.equal(Object.isFrozen(frozenObject.object.nested), true)
355
+ t.assert.strictEqual(Object.isFrozen(frozenObject), true)
356
+ t.assert.strictEqual(Object.isFrozen(frozenObject.object), true)
357
+ t.assert.strictEqual(Object.isFrozen(frozenObject.object.nested), true)
356
358
 
357
- t.pass()
359
+ t.assert.ok(true)
358
360
  } catch (error) {
359
- t.fail()
361
+ t.assert.fail()
360
362
  }
361
363
  })
362
364
 
363
365
  test('pluginTimeout should be parsed correctly', t => {
364
366
  const withDisabledTimeout = Fastify({ pluginTimeout: '0' })
365
- t.equal(withDisabledTimeout.initialConfig.pluginTimeout, 0)
367
+ t.assert.strictEqual(withDisabledTimeout.initialConfig.pluginTimeout, 0)
366
368
  const withInvalidTimeout = Fastify({ pluginTimeout: undefined })
367
- t.equal(withInvalidTimeout.initialConfig.pluginTimeout, 10000)
368
- t.end()
369
+ t.assert.strictEqual(withInvalidTimeout.initialConfig.pluginTimeout, 10000)
370
+ })
371
+
372
+ test('Should not mutate the options object outside Fastify', async t => {
373
+ const options = Object.freeze({})
374
+
375
+ try {
376
+ Fastify(options)
377
+ t.assert.ok(true)
378
+ } catch (error) {
379
+ t.assert.fail(error.message)
380
+ }
369
381
  })
@@ -1,34 +1,34 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
3
+ const { test } = require('node:test')
5
4
  const Fastify = require('../..')
6
- const loggerUtils = require('../../lib/logger')
5
+ const loggerUtils = require('../../lib/logger-factory')
6
+ const { serializers } = require('../../lib/logger-pino')
7
7
 
8
8
  test('time resolution', t => {
9
9
  t.plan(2)
10
- t.equal(typeof loggerUtils.now, 'function')
11
- t.equal(typeof loggerUtils.now(), 'number')
10
+ t.assert.strictEqual(typeof loggerUtils.now, 'function')
11
+ t.assert.strictEqual(typeof loggerUtils.now(), 'number')
12
12
  })
13
13
 
14
- test('The logger should add a unique id for every request', t => {
14
+ test('The logger should add a unique id for every request', (t, done) => {
15
15
  const ids = []
16
16
 
17
17
  const fastify = Fastify()
18
18
  fastify.get('/', (req, reply) => {
19
- t.ok(req.id)
19
+ t.assert.ok(req.id)
20
20
  reply.send({ id: req.id })
21
21
  })
22
22
 
23
23
  fastify.listen({ port: 0 }, err => {
24
- t.error(err)
24
+ t.assert.ifError(err)
25
25
  const queue = new Queue()
26
26
  for (let i = 0; i < 10; i++) {
27
27
  queue.add(checkId)
28
28
  }
29
29
  queue.add(() => {
30
30
  fastify.close()
31
- t.end()
31
+ done()
32
32
  })
33
33
  })
34
34
 
@@ -37,24 +37,24 @@ test('The logger should add a unique id for every request', t => {
37
37
  method: 'GET',
38
38
  url: 'http://localhost:' + fastify.server.address().port
39
39
  }, (err, res) => {
40
- t.error(err)
40
+ t.assert.ifError(err)
41
41
  const payload = JSON.parse(res.payload)
42
- t.ok(ids.indexOf(payload.id) === -1, 'the id should not be duplicated')
42
+ t.assert.ok(ids.indexOf(payload.id) === -1, 'the id should not be duplicated')
43
43
  ids.push(payload.id)
44
44
  done()
45
45
  })
46
46
  }
47
47
  })
48
48
 
49
- test('The logger should not reuse request id header for req.id', t => {
49
+ test('The logger should not reuse request id header for req.id', (t, done) => {
50
50
  const fastify = Fastify()
51
51
  fastify.get('/', (req, reply) => {
52
- t.ok(req.id)
52
+ t.assert.ok(req.id)
53
53
  reply.send({ id: req.id })
54
54
  })
55
55
 
56
56
  fastify.listen({ port: 0 }, err => {
57
- t.error(err)
57
+ t.assert.ifError(err)
58
58
 
59
59
  fastify.inject({
60
60
  method: 'GET',
@@ -63,27 +63,27 @@ test('The logger should not reuse request id header for req.id', t => {
63
63
  'Request-Id': 'request-id-1'
64
64
  }
65
65
  }, (err, res) => {
66
- t.error(err)
66
+ t.assert.ifError(err)
67
67
  const payload = JSON.parse(res.payload)
68
- t.ok(payload.id !== 'request-id-1', 'the request id from the header should not be returned with default configuration')
69
- t.ok(payload.id === 'req-1') // first request id when using the default configuration
68
+ t.assert.ok(payload.id !== 'request-id-1', 'the request id from the header should not be returned with default configuration')
69
+ t.assert.ok(payload.id === 'req-1') // first request id when using the default configuration
70
70
  fastify.close()
71
- t.end()
71
+ done()
72
72
  })
73
73
  })
74
74
  })
75
75
 
76
- test('The logger should reuse request id header for req.id if requestIdHeader is set', t => {
76
+ test('The logger should reuse request id header for req.id if requestIdHeader is set', (t, done) => {
77
77
  const fastify = Fastify({
78
78
  requestIdHeader: 'request-id'
79
79
  })
80
80
  fastify.get('/', (req, reply) => {
81
- t.ok(req.id)
81
+ t.assert.ok(req.id)
82
82
  reply.send({ id: req.id })
83
83
  })
84
84
 
85
85
  fastify.listen({ port: 0 }, err => {
86
- t.error(err)
86
+ t.assert.ifError(err)
87
87
 
88
88
  fastify.inject({
89
89
  method: 'GET',
@@ -92,11 +92,11 @@ test('The logger should reuse request id header for req.id if requestIdHeader is
92
92
  'Request-Id': 'request-id-1'
93
93
  }
94
94
  }, (err, res) => {
95
- t.error(err)
95
+ t.assert.ifError(err)
96
96
  const payload = JSON.parse(res.payload)
97
- t.ok(payload.id === 'request-id-1', 'the request id from the header should be returned')
97
+ t.assert.ok(payload.id === 'request-id-1', 'the request id from the header should be returned')
98
98
  fastify.close()
99
- t.end()
99
+ done()
100
100
  })
101
101
  })
102
102
  })
@@ -137,22 +137,22 @@ test('The logger should error if both stream and file destination are given', t
137
137
  }
138
138
  })
139
139
  } catch (err) {
140
- t.equal(err.code, 'FST_ERR_LOG_INVALID_DESTINATION')
141
- t.equal(err.message, 'Cannot specify both logger.stream and logger.file options')
140
+ t.assert.strictEqual(err.code, 'FST_ERR_LOG_INVALID_DESTINATION')
141
+ t.assert.strictEqual(err.message, 'Cannot specify both logger.stream and logger.file options')
142
142
  }
143
143
  })
144
144
 
145
145
  test('The serializer prevent fails if the request socket is undefined', t => {
146
146
  t.plan(1)
147
147
 
148
- const serialized = loggerUtils.serializers.req({
148
+ const serialized = serializers.req({
149
149
  method: 'GET',
150
150
  url: '/',
151
151
  socket: undefined,
152
152
  headers: {}
153
153
  })
154
154
 
155
- t.same(serialized, {
155
+ t.assert.deepStrictEqual(serialized, {
156
156
  method: 'GET',
157
157
  url: '/',
158
158
  version: undefined,
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
3
+ const { test } = require('node:test')
5
4
 
6
5
  const pluginUtilsPublic = require('../../lib/pluginUtils.js')
7
6
  const symbols = require('../../lib/symbols.js')
@@ -12,8 +11,8 @@ test("shouldSkipOverride should check the 'skip-override' symbol", t => {
12
11
 
13
12
  yes[Symbol.for('skip-override')] = true
14
13
 
15
- t.ok(pluginUtils.shouldSkipOverride(yes))
16
- t.notOk(pluginUtils.shouldSkipOverride(no))
14
+ t.assert.ok(pluginUtils.shouldSkipOverride(yes))
15
+ t.assert.ok(!pluginUtils.shouldSkipOverride(no))
17
16
 
18
17
  function yes () {}
19
18
  function no () {}
@@ -26,7 +25,7 @@ test('getPluginName should return plugin name if the file is cached', t => {
26
25
  require.cache[expectedPluginName] = { exports: fn }
27
26
  const pluginName = pluginUtilsPublic.getPluginName(fn)
28
27
 
29
- t.equal(pluginName, expectedPluginName)
28
+ t.assert.strictEqual(pluginName, expectedPluginName)
30
29
  })
31
30
 
32
31
  test('getPluginName should not throw when require.cache is undefined', t => {
@@ -36,12 +35,12 @@ test('getPluginName should not throw when require.cache is undefined', t => {
36
35
  }
37
36
  const cache = require.cache
38
37
  require.cache = undefined
39
- t.teardown(() => {
38
+ t.after(() => {
40
39
  require.cache = cache
41
40
  })
42
41
  const pluginName = pluginUtilsPublic.getPluginName(example)
43
42
 
44
- t.equal(pluginName, 'example')
43
+ t.assert.strictEqual(pluginName, 'example')
45
44
  })
46
45
 
47
46
  test("getMeta should return the object stored with the 'plugin-meta' symbol", t => {
@@ -50,7 +49,7 @@ test("getMeta should return the object stored with the 'plugin-meta' symbol", t
50
49
  const meta = { hello: 'world' }
51
50
  fn[Symbol.for('plugin-meta')] = meta
52
51
 
53
- t.same(meta, pluginUtils.getMeta(fn))
52
+ t.assert.deepStrictEqual(meta, pluginUtils.getMeta(fn))
54
53
 
55
54
  function fn () {}
56
55
  })
@@ -73,9 +72,9 @@ test('checkDecorators should check if the given decorator is present in the inst
73
72
 
74
73
  try {
75
74
  pluginUtils.checkDecorators.call(context, fn)
76
- t.pass('Everything ok')
75
+ t.assert.ok('Everything ok')
77
76
  } catch (err) {
78
- t.fail(err)
77
+ t.assert.fail(err)
79
78
  }
80
79
 
81
80
  function fn () {}
@@ -99,9 +98,9 @@ test('checkDecorators should check if the given decorator is present in the inst
99
98
 
100
99
  try {
101
100
  pluginUtils.checkDecorators.call(context, fn)
102
- t.fail('should throw')
101
+ t.assert.fail('should throw')
103
102
  } catch (err) {
104
- t.equal(err.message, "The decorator 'plugin' is not present in Request")
103
+ t.assert.strictEqual(err.message, "The decorator 'plugin' is not present in Request")
105
104
  }
106
105
 
107
106
  function fn () {}
@@ -121,9 +120,9 @@ test('checkDecorators should accept optional decorators', t => {
121
120
 
122
121
  try {
123
122
  pluginUtils.checkDecorators.call(context, fn)
124
- t.pass('Everything ok')
123
+ t.assert.ok('Everything ok')
125
124
  } catch (err) {
126
- t.fail(err)
125
+ t.assert.fail(err)
127
126
  }
128
127
 
129
128
  function fn () {}
@@ -141,9 +140,9 @@ test('checkDependencies should check if the given dependency is present in the i
141
140
 
142
141
  try {
143
142
  pluginUtils.checkDependencies.call(context, fn)
144
- t.pass('Everything ok')
143
+ t.assert.ok('Everything ok')
145
144
  } catch (err) {
146
- t.fail(err)
145
+ t.assert.fail(err)
147
146
  }
148
147
 
149
148
  function fn () {}
@@ -162,9 +161,9 @@ test('checkDependencies should check if the given dependency is present in the i
162
161
 
163
162
  try {
164
163
  pluginUtils.checkDependencies.call(context, fn)
165
- t.fail('should throw')
164
+ t.assert.fail('should throw')
166
165
  } catch (err) {
167
- t.equal(err.message, "The dependency 'plugin' of plugin 'test-plugin' is not registered")
166
+ t.assert.strictEqual(err.message, "The dependency 'plugin' of plugin 'test-plugin' is not registered")
168
167
  }
169
168
 
170
169
  function fn () {}