fastify 5.8.5 → 5.10.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 (126) hide show
  1. package/PROJECT_CHARTER.md +1 -1
  2. package/README.md +7 -10
  3. package/SECURITY.md +1 -1
  4. package/SPONSORS.md +6 -4
  5. package/build/build-validation.js +2 -2
  6. package/docs/Guides/Database.md +0 -28
  7. package/docs/Guides/Delay-Accepting-Requests.md +1 -1
  8. package/docs/Guides/Ecosystem.md +23 -9
  9. package/docs/Guides/Getting-Started.md +2 -2
  10. package/docs/Guides/Migration-Guide-V4.md +2 -2
  11. package/docs/Guides/Migration-Guide-V5.md +1 -1
  12. package/docs/Guides/Plugins-Guide.md +1 -1
  13. package/docs/Guides/Prototype-Poisoning.md +3 -3
  14. package/docs/Guides/Serverless.md +8 -15
  15. package/docs/Guides/Style-Guide.md +1 -1
  16. package/docs/Guides/Write-Plugin.md +1 -1
  17. package/docs/Reference/Encapsulation.md +27 -26
  18. package/docs/Reference/Errors.md +12 -4
  19. package/docs/Reference/HTTP2.md +10 -10
  20. package/docs/Reference/Hooks.md +5 -5
  21. package/docs/Reference/Index.md +14 -16
  22. package/docs/Reference/LTS.md +12 -13
  23. package/docs/Reference/Lifecycle.md +9 -8
  24. package/docs/Reference/Logging.md +47 -39
  25. package/docs/Reference/Middleware.md +21 -25
  26. package/docs/Reference/Principles.md +2 -2
  27. package/docs/Reference/Reply.md +6 -1
  28. package/docs/Reference/Request.md +29 -18
  29. package/docs/Reference/Routes.md +5 -2
  30. package/docs/Reference/Server.md +138 -11
  31. package/docs/Reference/Type-Providers.md +53 -9
  32. package/docs/Reference/TypeScript.md +3 -3
  33. package/docs/Reference/Validation-and-Serialization.md +15 -2
  34. package/docs/Reference/Warnings.md +11 -6
  35. package/eslint.config.js +7 -2
  36. package/fastify.d.ts +13 -3
  37. package/fastify.js +60 -31
  38. package/lib/content-type-parser.js +2 -0
  39. package/lib/content-type.js +34 -1
  40. package/lib/context.js +0 -3
  41. package/lib/decorate.js +11 -3
  42. package/lib/error-handler.js +10 -28
  43. package/lib/error-serializer.js +59 -59
  44. package/lib/errors.js +23 -1
  45. package/lib/four-oh-four.js +22 -19
  46. package/lib/handle-request.js +12 -5
  47. package/lib/log-controller.js +169 -0
  48. package/lib/logger-factory.js +25 -4
  49. package/lib/plugin-override.js +2 -1
  50. package/lib/plugin-utils.js +5 -5
  51. package/lib/reply.js +96 -50
  52. package/lib/req-id-gen-factory.js +4 -1
  53. package/lib/request.js +16 -6
  54. package/lib/route.js +47 -41
  55. package/lib/schema-controller.js +1 -1
  56. package/lib/schemas.js +37 -30
  57. package/lib/symbols.js +4 -2
  58. package/lib/validation.js +10 -13
  59. package/lib/warnings.js +22 -4
  60. package/package.json +15 -17
  61. package/scripts/validate-ecosystem-links.js +1 -0
  62. package/test/bundler/esbuild/package.json +1 -1
  63. package/test/close-pipelining.test.js +1 -2
  64. package/test/content-type.test.js +20 -0
  65. package/test/custom-http-server.test.js +38 -0
  66. package/test/decorator-instance-properties.test.js +63 -0
  67. package/test/diagnostics-channel/async-error-handler.test.js +74 -0
  68. package/test/genReqId.test.js +24 -0
  69. package/test/hooks.test.js +94 -0
  70. package/test/http-methods/get.test.js +1 -1
  71. package/test/http2/plain.test.js +135 -0
  72. package/test/http2/secure-with-fallback.test.js +1 -1
  73. package/test/https/https.test.js +1 -2
  74. package/test/internals/errors.test.js +31 -1
  75. package/test/internals/logger.test.js +322 -0
  76. package/test/internals/plugin.test.js +3 -1
  77. package/test/internals/reply.test.js +35 -4
  78. package/test/internals/request.test.js +37 -10
  79. package/test/internals/schema-controller-perf.test.js +33 -0
  80. package/test/logger/logging.test.js +57 -1
  81. package/test/logger/options.test.js +38 -1
  82. package/test/reply-error.test.js +1 -1
  83. package/test/reply-trailers.test.js +70 -0
  84. package/test/request-media-type.test.js +105 -0
  85. package/test/route-prefix.test.js +34 -0
  86. package/test/router-options.test.js +222 -11
  87. package/test/schema-serialization.test.js +108 -0
  88. package/test/schema-validation.test.js +24 -0
  89. package/test/scripts/validate-ecosystem-links.test.js +40 -57
  90. package/test/stream.4.test.js +2 -2
  91. package/test/throw.test.js +14 -0
  92. package/test/trust-proxy.test.js +70 -30
  93. package/test/types/content-type-parser.tst.ts +70 -0
  94. package/test/types/{decorate-request-reply.test-d.ts → decorate-request-reply.tst.ts} +4 -4
  95. package/test/types/{dummy-plugin.ts → dummy-plugin.mts} +1 -1
  96. package/test/types/errors.tst.ts +91 -0
  97. package/test/types/fastify.tst.ts +351 -0
  98. package/test/types/hooks.tst.ts +578 -0
  99. package/test/types/instance.tst.ts +597 -0
  100. package/test/types/{logger.test-d.ts → logger.tst.ts} +61 -62
  101. package/test/types/plugin.tst.ts +96 -0
  102. package/test/types/register.tst.ts +245 -0
  103. package/test/types/reply.tst.ts +297 -0
  104. package/test/types/request.tst.ts +199 -0
  105. package/test/types/route.tst.ts +576 -0
  106. package/test/types/{schema.test-d.ts → schema.tst.ts} +22 -22
  107. package/test/types/{serverFactory.test-d.ts → serverFactory.tst.ts} +4 -4
  108. package/test/types/tsconfig.json +9 -0
  109. package/test/types/{type-provider.test-d.ts → type-provider.tst.ts} +256 -250
  110. package/test/types/using.tst.ts +14 -0
  111. package/types/errors.d.ts +4 -0
  112. package/types/instance.d.ts +2 -0
  113. package/types/logger.d.ts +22 -0
  114. package/types/request.d.ts +23 -2
  115. package/test/types/content-type-parser.test-d.ts +0 -72
  116. package/test/types/errors.test-d.ts +0 -90
  117. package/test/types/fastify.test-d.ts +0 -352
  118. package/test/types/hooks.test-d.ts +0 -550
  119. package/test/types/import.ts +0 -2
  120. package/test/types/instance.test-d.ts +0 -588
  121. package/test/types/plugin.test-d.ts +0 -97
  122. package/test/types/register.test-d.ts +0 -237
  123. package/test/types/reply.test-d.ts +0 -254
  124. package/test/types/request.test-d.ts +0 -188
  125. package/test/types/route.test-d.ts +0 -553
  126. package/test/types/using.test-d.ts +0 -17
@@ -1,39 +1,40 @@
1
1
  import * as fs from 'node:fs'
2
2
  import { IncomingMessage, Server, ServerResponse } from 'node:http'
3
3
  import P from 'pino'
4
- import { expectAssignable, expectDeprecated, expectError, expectNotAssignable, expectType } from 'tsd'
4
+ import { expect } from 'tstyche'
5
5
  import fastify, {
6
6
  FastifyBaseLogger,
7
+ FastifyError,
7
8
  FastifyLogFn,
8
9
  FastifyReply,
9
10
  FastifyRequest,
10
11
  LogLevel
11
- } from '../../fastify'
12
- import { FastifyLoggerInstance, ResSerializerReply } from '../../types/logger'
12
+ } from '../../fastify.js'
13
+ import { ResSerializerReply } from '../../types/logger.js'
13
14
 
14
- expectType<FastifyBaseLogger>(fastify().log)
15
+ expect(fastify().log).type.toBe<FastifyBaseLogger>()
15
16
 
16
17
  class Foo { }
17
18
 
18
19
  ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(logLevel => {
19
- expectType<FastifyLogFn>(
20
+ expect(
20
21
  fastify<Server, IncomingMessage, ServerResponse, FastifyBaseLogger>().log[logLevel as LogLevel]
21
- )
22
- expectType<void>(
22
+ ).type.toBe<FastifyLogFn>()
23
+ expect(
23
24
  fastify<Server, IncomingMessage, ServerResponse, FastifyBaseLogger>().log[logLevel as LogLevel]('')
24
- )
25
- expectType<void>(
25
+ ).type.toBe<void>()
26
+ expect(
26
27
  fastify<Server, IncomingMessage, ServerResponse, FastifyBaseLogger>().log[logLevel as LogLevel]({})
27
- )
28
- expectType<void>(
28
+ ).type.toBe<void>()
29
+ expect(
29
30
  fastify<Server, IncomingMessage, ServerResponse, FastifyBaseLogger>().log[logLevel as LogLevel]({ foo: 'bar' })
30
- )
31
- expectType<void>(
31
+ ).type.toBe<void>()
32
+ expect(
32
33
  fastify<Server, IncomingMessage, ServerResponse, FastifyBaseLogger>().log[logLevel as LogLevel](new Error())
33
- )
34
- expectType<void>(
34
+ ).type.toBe<void>()
35
+ expect(
35
36
  fastify<Server, IncomingMessage, ServerResponse, FastifyBaseLogger>().log[logLevel as LogLevel](new Foo())
36
- )
37
+ ).type.toBe<void>()
37
38
  })
38
39
 
39
40
  interface CustomLogger extends FastifyBaseLogger {
@@ -68,7 +69,7 @@ const serverWithCustomLogger = fastify<
68
69
  CustomLoggerImpl
69
70
  >({ logger: customLogger })
70
71
 
71
- expectType<CustomLoggerImpl>(serverWithCustomLogger.log)
72
+ expect(serverWithCustomLogger.log).type.toBe<CustomLoggerImpl>()
72
73
 
73
74
  const serverWithPino = fastify<
74
75
  Server,
@@ -82,20 +83,20 @@ const serverWithPino = fastify<
82
83
  })
83
84
  })
84
85
 
85
- expectType<P.Logger>(serverWithPino.log)
86
+ expect(serverWithPino.log).type.toBe<P.Logger>()
86
87
 
87
88
  serverWithPino.route({
88
89
  method: 'GET',
89
90
  url: '/',
90
91
  handler (request) {
91
- expectType<P.Logger>(this.log)
92
- expectType<P.Logger>(request.log)
92
+ expect(this.log).type.toBe<P.Logger>()
93
+ expect(request.log).type.toBe<P.Logger>()
93
94
  }
94
95
  })
95
96
 
96
97
  serverWithPino.get('/', function (request) {
97
- expectType<P.Logger>(this.log)
98
- expectType<P.Logger>(request.log)
98
+ expect(this.log).type.toBe<P.Logger>()
99
+ expect(request.log).type.toBe<P.Logger>()
99
100
  })
100
101
 
101
102
  const serverWithLogOptions = fastify<
@@ -108,7 +109,7 @@ const serverWithLogOptions = fastify<
108
109
  }
109
110
  })
110
111
 
111
- expectType<FastifyBaseLogger>(serverWithLogOptions.log)
112
+ expect(serverWithLogOptions.log).type.toBe<FastifyBaseLogger>()
112
113
 
113
114
  const serverWithFileOption = fastify<
114
115
  Server,
@@ -121,7 +122,7 @@ const serverWithFileOption = fastify<
121
122
  }
122
123
  })
123
124
 
124
- expectType<FastifyBaseLogger>(serverWithFileOption.log)
125
+ expect(serverWithFileOption.log).type.toBe<FastifyBaseLogger>()
125
126
 
126
127
  const serverAutoInferringTypes = fastify({
127
128
  logger: {
@@ -129,7 +130,7 @@ const serverAutoInferringTypes = fastify({
129
130
  }
130
131
  })
131
132
 
132
- expectType<FastifyBaseLogger>(serverAutoInferringTypes.log)
133
+ expect(serverAutoInferringTypes.log).type.toBe<FastifyBaseLogger>()
133
134
 
134
135
  const serverWithLoggerInstance = fastify({
135
136
  loggerInstance: P({
@@ -138,14 +139,14 @@ const serverWithLoggerInstance = fastify({
138
139
  })
139
140
  })
140
141
 
141
- expectType<P.Logger>(serverWithLoggerInstance.log)
142
+ expect(serverWithLoggerInstance.log).type.toBe<P.Logger>()
142
143
 
143
144
  const serverWithPinoConfig = fastify({
144
145
  logger: {
145
146
  level: 'info',
146
147
  serializers: {
147
- req (IncomingMessage) {
148
- expectType<FastifyRequest>(IncomingMessage)
148
+ req (request) {
149
+ expect(request).type.toBe<FastifyRequest>()
149
150
  return {
150
151
  method: 'method',
151
152
  url: 'url',
@@ -156,15 +157,17 @@ const serverWithPinoConfig = fastify({
156
157
  other: ''
157
158
  }
158
159
  },
159
- res (ServerResponse) {
160
- expectType<ResSerializerReply<Server, FastifyReply>>(ServerResponse)
161
- expectAssignable<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>(ServerResponse)
162
- expectNotAssignable<FastifyReply>(ServerResponse)
160
+ res (reply) {
161
+ expect(reply).type.toBe<ResSerializerReply<Server, FastifyReply>>()
162
+ expect(reply).type.toBeAssignableTo<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>()
163
+ expect(reply).type.not.toBeAssignableTo<FastifyReply>()
163
164
  return {
164
165
  statusCode: 'statusCode'
165
166
  }
166
167
  },
167
- err (FastifyError) {
168
+ err (error) {
169
+ expect(error).type.toBe<FastifyError>()
170
+
168
171
  return {
169
172
  other: '',
170
173
  type: 'type',
@@ -176,7 +179,7 @@ const serverWithPinoConfig = fastify({
176
179
  }
177
180
  })
178
181
 
179
- expectType<FastifyBaseLogger>(serverWithPinoConfig.log)
182
+ expect(serverWithPinoConfig.log).type.toBe<FastifyBaseLogger>()
180
183
 
181
184
  const serverAutoInferredFileOption = fastify({
182
185
  logger: {
@@ -185,15 +188,15 @@ const serverAutoInferredFileOption = fastify({
185
188
  }
186
189
  })
187
190
 
188
- expectType<FastifyBaseLogger>(serverAutoInferredFileOption.log)
191
+ expect(serverAutoInferredFileOption.log).type.toBe<FastifyBaseLogger>()
189
192
 
190
193
  const serverAutoInferredSerializerResponseObjectOption = fastify({
191
194
  logger: {
192
195
  serializers: {
193
- res (ServerResponse) {
194
- expectType<ResSerializerReply<Server, FastifyReply>>(ServerResponse)
195
- expectAssignable<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>(ServerResponse)
196
- expectNotAssignable<FastifyReply>(ServerResponse)
196
+ res (reply) {
197
+ expect(reply).type.toBe<ResSerializerReply<Server, FastifyReply>>()
198
+ expect(reply).type.toBeAssignableTo<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>()
199
+ expect(reply).type.not.toBeAssignableTo<FastifyReply>()
197
200
  return {
198
201
  status: '200'
199
202
  }
@@ -202,13 +205,13 @@ const serverAutoInferredSerializerResponseObjectOption = fastify({
202
205
  }
203
206
  })
204
207
 
205
- expectType<FastifyBaseLogger>(serverAutoInferredSerializerResponseObjectOption.log)
208
+ expect(serverAutoInferredSerializerResponseObjectOption.log).type.toBe<FastifyBaseLogger>()
206
209
 
207
210
  const serverAutoInferredSerializerObjectOption = fastify({
208
211
  logger: {
209
212
  serializers: {
210
- req (IncomingMessage) {
211
- expectType<FastifyRequest>(IncomingMessage)
213
+ req (request) {
214
+ expect(request).type.toBe<FastifyRequest>()
212
215
  return {
213
216
  method: 'method',
214
217
  url: 'url',
@@ -219,10 +222,10 @@ const serverAutoInferredSerializerObjectOption = fastify({
219
222
  other: ''
220
223
  }
221
224
  },
222
- res (ServerResponse) {
223
- expectType<ResSerializerReply<Server, FastifyReply>>(ServerResponse)
224
- expectAssignable<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>(ServerResponse)
225
- expectNotAssignable<FastifyReply>(ServerResponse)
225
+ res (reply) {
226
+ expect(reply).type.toBe<ResSerializerReply<Server, FastifyReply>>()
227
+ expect(reply).type.toBeAssignableTo<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>()
228
+ expect(reply).type.not.toBeAssignableTo<FastifyReply>()
226
229
  return {
227
230
  statusCode: 'statusCode'
228
231
  }
@@ -239,7 +242,7 @@ const serverAutoInferredSerializerObjectOption = fastify({
239
242
  }
240
243
  })
241
244
 
242
- expectType<FastifyBaseLogger>(serverAutoInferredSerializerObjectOption.log)
245
+ expect(serverAutoInferredSerializerObjectOption.log).type.toBe<FastifyBaseLogger>()
243
246
 
244
247
  const passStreamAsOption = fastify({
245
248
  logger: {
@@ -247,7 +250,7 @@ const passStreamAsOption = fastify({
247
250
  }
248
251
  })
249
252
 
250
- expectType<FastifyBaseLogger>(passStreamAsOption.log)
253
+ expect(passStreamAsOption.log).type.toBe<FastifyBaseLogger>()
251
254
 
252
255
  const passPinoOption = fastify({
253
256
  logger: {
@@ -258,20 +261,16 @@ const passPinoOption = fastify({
258
261
  }
259
262
  })
260
263
 
261
- expectType<FastifyBaseLogger>(passPinoOption.log)
262
-
263
- // FastifyLoggerInstance is deprecated
264
- expectDeprecated({} as FastifyLoggerInstance)
264
+ expect(passPinoOption.log).type.toBe<FastifyBaseLogger>()
265
265
 
266
266
  const childParent = fastify().log
267
267
  // we test different option variant here
268
- expectType<FastifyBaseLogger>(childParent.child({}, { level: 'info' }))
269
- expectType<FastifyBaseLogger>(childParent.child({}, { level: 'silent' }))
270
- expectType<FastifyBaseLogger>(childParent.child({}, { redact: ['pass', 'pin'] }))
271
- expectType<FastifyBaseLogger>(childParent.child({}, { serializers: { key: () => { } } }))
272
- expectType<FastifyBaseLogger>(childParent.child({}, { level: 'info', redact: ['pass', 'pin'], serializers: { key: () => { } } }))
273
-
274
- // no option pass
275
- expectError(childParent.child())
276
- // wrong option
277
- expectError(childParent.child({}, { nonExist: true }))
268
+ expect(childParent.child({}, { level: 'info' })).type.toBe<FastifyBaseLogger>()
269
+ expect(childParent.child({}, { level: 'silent' })).type.toBe<FastifyBaseLogger>()
270
+ expect(childParent.child({}, { redact: ['pass', 'pin'] })).type.toBe<FastifyBaseLogger>()
271
+ expect(childParent.child({}, { serializers: { key: () => { } } })).type.toBe<FastifyBaseLogger>()
272
+ expect(childParent.child({}, { level: 'info', redact: ['pass', 'pin'], serializers: { key: () => { } } })).type.toBe<FastifyBaseLogger>()
273
+
274
+ expect(childParent.child).type.not.toBeCallableWith()
275
+
276
+ expect(childParent.child).type.not.toBeCallableWith({}, { nonExist: true })
@@ -0,0 +1,96 @@
1
+ import * as http from 'node:http'
2
+ import * as https from 'node:https'
3
+ import { FastifyError } from '@fastify/error'
4
+ import { expect } from 'tstyche'
5
+ import fastify, { FastifyInstance, FastifyPluginOptions, SafePromiseLike } from '../../fastify.js'
6
+ import { FastifyPluginCallback, FastifyPluginAsync } from '../../types/plugin.js'
7
+
8
+ // FastifyPlugin & FastifyRegister
9
+ interface TestOptions extends FastifyPluginOptions {
10
+ option1: string;
11
+ option2: boolean;
12
+ }
13
+ const testOptions: TestOptions = {
14
+ option1: 'a',
15
+ option2: false
16
+ }
17
+ const testPluginOpts: FastifyPluginCallback<TestOptions> = function (instance, opts, done) {
18
+ expect(opts).type.toBe<TestOptions>()
19
+ }
20
+ const testPluginOptsAsync: FastifyPluginAsync<TestOptions> = async function (instance, opts) {
21
+ expect(opts).type.toBe<TestOptions>()
22
+ }
23
+
24
+ const testPluginOptsWithType = (
25
+ instance: FastifyInstance,
26
+ opts: FastifyPluginOptions,
27
+ done: (error?: FastifyError) => void
28
+ ) => { }
29
+ const testPluginOptsWithTypeAsync = async (
30
+ instance: FastifyInstance,
31
+ opts: FastifyPluginOptions
32
+ ) => { }
33
+
34
+ expect(fastify().register).type.not.toBeCallableWith(testPluginOpts, {}) // must provide required options
35
+ expect(fastify().register).type.not.toBeCallableWith(testPluginOptsAsync, {}) // must provide required options
36
+
37
+ expect(fastify().register(testPluginOpts, { option1: '', option2: true })).type.toBeAssignableTo<FastifyInstance>()
38
+ expect(fastify().register(testPluginOptsAsync, { option1: '', option2: true })).type.toBeAssignableTo<FastifyInstance>()
39
+
40
+ expect(fastify().register(function (instance, opts, done) { })).type.toBeAssignableTo<FastifyInstance>()
41
+ expect(fastify().register(function (instance, opts, done) { }, () => { })).type.toBeAssignableTo<FastifyInstance>()
42
+ expect(fastify().register(function (instance, opts, done) { }, { logLevel: 'info', prefix: 'foobar' })).type.toBeAssignableTo<FastifyInstance>()
43
+
44
+ expect(fastify().register(import('./dummy-plugin.mjs'))).type.toBeAssignableTo<FastifyInstance>()
45
+ expect(fastify().register(import('./dummy-plugin.mjs'), { foo: 1 })).type.toBeAssignableTo<FastifyInstance>()
46
+
47
+ const testPluginCallback: FastifyPluginCallback = function (instance, opts, done) { }
48
+ expect(fastify().register(testPluginCallback, {})).type.toBeAssignableTo<FastifyInstance>()
49
+
50
+ const testPluginAsync: FastifyPluginAsync = async function (instance, opts) { }
51
+ expect(fastify().register(testPluginAsync, {})).type.toBeAssignableTo<FastifyInstance>()
52
+
53
+ expect(
54
+ fastify().register(function (instance, opts): Promise<void> { return Promise.resolve() })
55
+ ).type.toBeAssignableTo<FastifyInstance>()
56
+ expect(fastify().register(async function (instance, opts) { }, () => { })).type.toBeAssignableTo<FastifyInstance>()
57
+ expect(fastify().register(async function (instance, opts) { }, { logLevel: 'info', prefix: 'foobar' })).type.toBeAssignableTo<FastifyInstance>()
58
+
59
+ expect(fastify().register).type.not.toBeCallableWith(function () { }, { logLevel: '', prefix: 'foobar' }) // must provide valid logLevel
60
+
61
+ const httpsServer = fastify({ https: {} })
62
+ expect(httpsServer).type.not.toBeAssignableTo<
63
+ FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> &
64
+ Promise<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>
65
+ >()
66
+ expect(httpsServer).type.toBeAssignableTo<
67
+ FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> &
68
+ PromiseLike<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>
69
+ >()
70
+ expect(httpsServer).type.toBe<
71
+ FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse> &
72
+ SafePromiseLike<FastifyInstance<https.Server, http.IncomingMessage, http.ServerResponse>>
73
+ >()
74
+
75
+ // Chainable
76
+ httpsServer
77
+ .register(testPluginOpts, testOptions)
78
+ .after((_error) => { })
79
+ .ready((_error) => { })
80
+ .close(() => { })
81
+
82
+ // Thenable
83
+ expect(httpsServer.after()).type.toBeAssignableTo<PromiseLike<undefined>>()
84
+ expect(httpsServer.close()).type.toBeAssignableTo<PromiseLike<undefined>>()
85
+ expect(httpsServer.ready()).type.toBeAssignableTo<PromiseLike<undefined>>()
86
+ expect(httpsServer.register(testPluginOpts, testOptions)).type.toBeAssignableTo<PromiseLike<undefined>>()
87
+ expect(httpsServer.register(testPluginOptsWithType)).type.toBeAssignableTo<PromiseLike<undefined>>()
88
+ expect(httpsServer.register(testPluginOptsWithTypeAsync)).type.toBeAssignableTo<PromiseLike<undefined>>()
89
+ expect(httpsServer.register(testPluginOptsWithType, { prefix: '/test' })).type.toBeAssignableTo<PromiseLike<undefined>>()
90
+ expect(httpsServer.register(testPluginOptsWithTypeAsync, { prefix: '/test' })).type.toBeAssignableTo<PromiseLike<undefined>>()
91
+
92
+ async function testAsync (): Promise<void> {
93
+ await httpsServer
94
+ .register(testPluginOpts, testOptions)
95
+ .register(testPluginOpts, testOptions)
96
+ }
@@ -0,0 +1,245 @@
1
+ import { IncomingMessage, Server, ServerResponse } from 'node:http'
2
+ import { Http2Server, Http2ServerRequest, Http2ServerResponse } from 'node:http2'
3
+ import { expect } from 'tstyche'
4
+ import fastify, {
5
+ FastifyInstance,
6
+ FastifyError,
7
+ FastifyBaseLogger,
8
+ FastifyPluginAsync,
9
+ FastifyPluginCallback,
10
+ FastifyPluginOptions,
11
+ RawServerDefault
12
+ } from '../../fastify.js'
13
+
14
+ const testPluginCallback: FastifyPluginCallback = function (instance, opts, done) { }
15
+ const testPluginAsync: FastifyPluginAsync = async function (instance, opts) { }
16
+
17
+ const testPluginOpts: FastifyPluginCallback = function (instance, opts, done) { }
18
+ const testPluginOptsAsync: FastifyPluginAsync = async function (instance, opts) { }
19
+
20
+ const testPluginOptsWithType = (
21
+ instance: FastifyInstance,
22
+ opts: FastifyPluginOptions,
23
+ done: (error?: FastifyError) => void
24
+ ) => { }
25
+ const testPluginOptsWithTypeAsync = async (instance: FastifyInstance, opts: FastifyPluginOptions) => { }
26
+
27
+ interface TestOptions extends FastifyPluginOptions {
28
+ option1: string;
29
+ option2: boolean;
30
+ }
31
+
32
+ // Type validation
33
+ expect(fastify().register).type.not.toBeCallableWith(testPluginOptsAsync, { prefix: 1 })
34
+ expect(fastify().register).type.not.toBeCallableWith(testPluginOptsAsync, { logLevel: () => ({}) })
35
+ expect(fastify().register).type.not.toBeCallableWith(testPluginOptsAsync, { logSerializers: () => ({}) })
36
+ expect(fastify().register).type.not.toBeCallableWith({})
37
+
38
+ expect(
39
+ fastify().register(
40
+ testPluginOptsAsync, { prefix: '/example', logLevel: 'info', logSerializers: { key: (value: any) => `${value}` } }
41
+ )
42
+ ).type.toBeAssignableTo<FastifyInstance>()
43
+
44
+ expect(
45
+ fastify().register(testPluginOptsAsync, () => {
46
+ return {}
47
+ })
48
+ ).type.toBeAssignableTo<FastifyInstance>()
49
+
50
+ expect(
51
+ fastify().register(testPluginOptsAsync, (instance) => {
52
+ expect(instance).type.toBe<FastifyInstance>()
53
+ })
54
+ ).type.toBeAssignableTo<FastifyInstance>()
55
+
56
+ // With Http2
57
+ const serverWithHttp2 = fastify({ http2: true })
58
+ type ServerWithHttp2 = FastifyInstance<Http2Server, Http2ServerRequest, Http2ServerResponse>
59
+ const testPluginWithHttp2: FastifyPluginCallback<TestOptions, Http2Server> = function (instance, opts, done) { }
60
+ const testPluginWithHttp2Async: FastifyPluginAsync<TestOptions, Http2Server> = async function (instance, opts) { }
61
+ const testPluginWithHttp2WithType = (
62
+ instance: ServerWithHttp2,
63
+ opts: FastifyPluginOptions,
64
+ done: (error?: FastifyError) => void
65
+ ) => { }
66
+ const testPluginWithHttp2WithTypeAsync = async (
67
+ instance: ServerWithHttp2,
68
+ opts: FastifyPluginOptions
69
+ ) => { }
70
+ const testOptions: TestOptions = {
71
+ option1: 'a',
72
+ option2: false
73
+ }
74
+ expect(serverWithHttp2.register(testPluginCallback)).type.toBeAssignableTo<ServerWithHttp2>()
75
+ expect(serverWithHttp2.register(testPluginAsync)).type.toBeAssignableTo<ServerWithHttp2>()
76
+ expect(serverWithHttp2.register(testPluginOpts)).type.toBeAssignableTo<ServerWithHttp2>()
77
+ expect(serverWithHttp2.register(testPluginOptsAsync)).type.toBeAssignableTo<ServerWithHttp2>()
78
+ expect(serverWithHttp2.register(testPluginOptsWithType)).type.toBeAssignableTo<ServerWithHttp2>()
79
+ expect(serverWithHttp2.register(testPluginOptsWithTypeAsync)).type.toBeAssignableTo<ServerWithHttp2>()
80
+ expect(serverWithHttp2.register).type.not.toBeCallableWith(testPluginWithHttp2)
81
+ expect(serverWithHttp2.register(testPluginWithHttp2, testOptions)).type.toBeAssignableTo<ServerWithHttp2>()
82
+ expect(serverWithHttp2.register).type.not.toBeCallableWith(testPluginWithHttp2Async)
83
+ expect(serverWithHttp2.register(testPluginWithHttp2Async, testOptions)).type.toBeAssignableTo<ServerWithHttp2>()
84
+ expect(serverWithHttp2.register(testPluginWithHttp2WithType)).type.toBeAssignableTo<ServerWithHttp2>()
85
+ expect(serverWithHttp2.register(testPluginWithHttp2WithTypeAsync)).type.toBeAssignableTo<ServerWithHttp2>()
86
+ expect(serverWithHttp2.register((instance) => {
87
+ expect(instance).type.toBe<FastifyInstance>()
88
+ })).type.toBeAssignableTo<ServerWithHttp2>()
89
+ expect(serverWithHttp2.register((instance: ServerWithHttp2) => {
90
+ expect(instance).type.toBe<ServerWithHttp2>()
91
+ })).type.toBeAssignableTo<ServerWithHttp2>()
92
+ expect(serverWithHttp2.register(async (instance) => {
93
+ expect(instance).type.toBe<FastifyInstance>()
94
+ })).type.toBeAssignableTo<ServerWithHttp2>()
95
+ expect(serverWithHttp2.register(async (instance: ServerWithHttp2) => {
96
+ expect(instance).type.toBe<ServerWithHttp2>()
97
+ })).type.toBeAssignableTo<ServerWithHttp2>()
98
+
99
+ // With Type Provider
100
+ type TestTypeProvider = { schema: 'test', validator: 'test', serializer: 'test' }
101
+ const serverWithTypeProvider = fastify().withTypeProvider<TestTypeProvider>()
102
+ type ServerWithTypeProvider = FastifyInstance<
103
+ Server,
104
+ IncomingMessage,
105
+ ServerResponse,
106
+ FastifyBaseLogger,
107
+ TestTypeProvider
108
+ >
109
+ const testPluginWithTypeProvider: FastifyPluginCallback<
110
+ TestOptions,
111
+ RawServerDefault,
112
+ TestTypeProvider
113
+ > = function (instance, opts, done) { }
114
+ const testPluginWithTypeProviderAsync: FastifyPluginAsync<
115
+ TestOptions,
116
+ RawServerDefault,
117
+ TestTypeProvider
118
+ > = async function (instance, opts) { }
119
+ const testPluginWithTypeProviderWithType = (
120
+ instance: ServerWithTypeProvider,
121
+ opts: FastifyPluginOptions,
122
+ done: (error?: FastifyError) => void
123
+ ) => { }
124
+ const testPluginWithTypeProviderWithTypeAsync = async (
125
+ instance: ServerWithTypeProvider,
126
+ opts: FastifyPluginOptions
127
+ ) => { }
128
+ expect(serverWithTypeProvider.register(testPluginCallback)).type.toBeAssignableTo<ServerWithTypeProvider>()
129
+ expect(serverWithTypeProvider.register(testPluginAsync)).type.toBeAssignableTo<ServerWithTypeProvider>()
130
+ expect(serverWithTypeProvider.register(testPluginOpts)).type.toBeAssignableTo<ServerWithTypeProvider>()
131
+ expect(serverWithTypeProvider.register(testPluginOptsAsync)).type.toBeAssignableTo<ServerWithTypeProvider>()
132
+ expect(serverWithTypeProvider.register(testPluginOptsWithType)).type.toBeAssignableTo<ServerWithTypeProvider>()
133
+ expect(serverWithTypeProvider.register(testPluginOptsWithTypeAsync)).type.toBeAssignableTo<ServerWithTypeProvider>()
134
+ expect(serverWithTypeProvider.register).type.not.toBeCallableWith(testPluginWithTypeProvider)
135
+ expect(serverWithTypeProvider.register(testPluginWithTypeProvider, testOptions))
136
+ .type.toBeAssignableTo<ServerWithTypeProvider>()
137
+ expect(serverWithTypeProvider.register).type.not.toBeCallableWith(testPluginWithTypeProviderAsync)
138
+ expect(serverWithTypeProvider.register(testPluginWithTypeProviderAsync, testOptions))
139
+ .type.toBeAssignableTo<ServerWithTypeProvider>()
140
+ expect(serverWithTypeProvider.register(testPluginWithTypeProviderWithType))
141
+ .type.toBeAssignableTo<ServerWithTypeProvider>()
142
+ expect(serverWithTypeProvider.register(testPluginWithTypeProviderWithTypeAsync))
143
+ .type.toBeAssignableTo<ServerWithTypeProvider>()
144
+ expect(serverWithTypeProvider.register((instance) => {
145
+ expect(instance).type.toBe<FastifyInstance>()
146
+ })).type.toBeAssignableTo<ServerWithTypeProvider>()
147
+ expect(serverWithTypeProvider.register((instance: ServerWithTypeProvider) => {
148
+ expect(instance).type.toBe<ServerWithTypeProvider>()
149
+ })).type.toBeAssignableTo<ServerWithTypeProvider>()
150
+ expect(serverWithTypeProvider.register(async (instance) => {
151
+ expect(instance).type.toBe<FastifyInstance>()
152
+ })).type.toBeAssignableTo<ServerWithTypeProvider>()
153
+ expect(serverWithTypeProvider.register(async (instance: ServerWithTypeProvider) => {
154
+ expect(instance).type.toBe<ServerWithTypeProvider>()
155
+ })).type.toBeAssignableTo<ServerWithTypeProvider>()
156
+
157
+ // With Type Provider and logger
158
+ const customLogger = {
159
+ level: 'info',
160
+ info: () => { },
161
+ warn: () => { },
162
+ error: () => { },
163
+ fatal: () => { },
164
+ trace: () => { },
165
+ debug: () => { },
166
+ child: () => customLogger,
167
+ silent: () => { }
168
+ }
169
+ const serverWithTypeProviderAndLogger = fastify({
170
+ loggerInstance: customLogger
171
+ }).withTypeProvider<TestTypeProvider>()
172
+ type ServerWithTypeProviderAndLogger = FastifyInstance<
173
+ Server,
174
+ IncomingMessage,
175
+ ServerResponse,
176
+ typeof customLogger,
177
+ TestTypeProvider
178
+ >
179
+ const testPluginWithTypeProviderAndLogger: FastifyPluginCallback<
180
+ TestOptions,
181
+ RawServerDefault,
182
+ TestTypeProvider,
183
+ typeof customLogger
184
+ > = function (instance, opts, done) { }
185
+ const testPluginWithTypeProviderAndLoggerAsync: FastifyPluginAsync<
186
+ TestOptions,
187
+ RawServerDefault,
188
+ TestTypeProvider,
189
+ typeof customLogger
190
+ > = async function (instance, opts) { }
191
+ const testPluginWithTypeProviderAndLoggerWithType = (
192
+ instance: ServerWithTypeProviderAndLogger,
193
+ opts: FastifyPluginOptions,
194
+ done: (error?: FastifyError) => void
195
+ ) => { }
196
+ const testPluginWithTypeProviderAndLoggerWithTypeAsync = async (
197
+ instance: ServerWithTypeProviderAndLogger,
198
+ opts: FastifyPluginOptions
199
+ ) => { }
200
+ expect(serverWithTypeProviderAndLogger.register(testPluginCallback))
201
+ .type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
202
+ expect(serverWithTypeProviderAndLogger.register(testPluginAsync))
203
+ .type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
204
+ expect(serverWithTypeProviderAndLogger.register(testPluginOpts))
205
+ .type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
206
+ expect(serverWithTypeProviderAndLogger.register(testPluginOptsAsync))
207
+ .type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
208
+ expect(serverWithTypeProviderAndLogger.register(testPluginOptsWithType))
209
+ .type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
210
+ expect(serverWithTypeProviderAndLogger.register(testPluginOptsWithTypeAsync))
211
+ .type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
212
+ expect(serverWithTypeProviderAndLogger.register).type.not.toBeCallableWith(testPluginWithTypeProviderAndLogger)
213
+ expect(
214
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLogger, testOptions)
215
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
216
+ expect(serverWithTypeProviderAndLogger.register).type.not.toBeCallableWith(testPluginWithTypeProviderAndLoggerAsync)
217
+ expect(
218
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerAsync, testOptions)
219
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
220
+ expect(
221
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerWithType)
222
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
223
+ expect(
224
+ serverWithTypeProviderAndLogger.register(testPluginWithTypeProviderAndLoggerWithTypeAsync)
225
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
226
+ expect(
227
+ serverWithTypeProviderAndLogger.register((instance) => {
228
+ expect(instance).type.toBe<FastifyInstance>()
229
+ })
230
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
231
+ expect(
232
+ serverWithTypeProviderAndLogger.register((instance: ServerWithTypeProviderAndLogger) => {
233
+ expect(instance).type.toBe<ServerWithTypeProviderAndLogger>()
234
+ })
235
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
236
+ expect(
237
+ serverWithTypeProviderAndLogger.register(async (instance) => {
238
+ expect(instance).type.toBe<FastifyInstance>()
239
+ })
240
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()
241
+ expect(
242
+ serverWithTypeProviderAndLogger.register(async (instance: ServerWithTypeProviderAndLogger) => {
243
+ expect(instance).type.toBe<ServerWithTypeProviderAndLogger>()
244
+ })
245
+ ).type.toBeAssignableTo<ServerWithTypeProviderAndLogger>()