fastify 3.27.4 → 4.0.0-alpha.3

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 (168) hide show
  1. package/.taprc +3 -0
  2. package/README.md +7 -7
  3. package/build/build-error-serializer.js +27 -0
  4. package/build/build-validation.js +47 -35
  5. package/docs/Guides/Database.md +320 -0
  6. package/docs/Guides/Ecosystem.md +9 -0
  7. package/docs/Guides/Getting-Started.md +7 -7
  8. package/docs/Guides/Plugins-Guide.md +1 -1
  9. package/docs/Guides/Serverless.md +3 -3
  10. package/docs/Guides/Testing.md +2 -2
  11. package/docs/Migration-Guide-V4.md +12 -0
  12. package/docs/Reference/ContentTypeParser.md +4 -0
  13. package/docs/Reference/Decorators.md +2 -2
  14. package/docs/Reference/Encapsulation.md +2 -2
  15. package/docs/Reference/Errors.md +51 -6
  16. package/docs/Reference/HTTP2.md +3 -3
  17. package/docs/Reference/Hooks.md +4 -7
  18. package/docs/Reference/LTS.md +5 -4
  19. package/docs/Reference/Plugins.md +3 -3
  20. package/docs/Reference/Reply.md +73 -22
  21. package/docs/Reference/Request.md +1 -3
  22. package/docs/Reference/Routes.md +22 -15
  23. package/docs/Reference/Server.md +69 -119
  24. package/docs/Reference/TypeScript.md +20 -22
  25. package/docs/Reference/Validation-and-Serialization.md +30 -55
  26. package/docs/Type-Providers.md +257 -0
  27. package/examples/asyncawait.js +1 -1
  28. package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
  29. package/examples/benchmark/hooks-benchmark.js +1 -1
  30. package/examples/benchmark/simple.js +1 -1
  31. package/examples/hooks.js +2 -2
  32. package/examples/http2.js +1 -1
  33. package/examples/https.js +1 -1
  34. package/examples/parser.js +13 -3
  35. package/examples/route-prefix.js +1 -1
  36. package/examples/shared-schema.js +1 -1
  37. package/examples/simple-stream.js +18 -0
  38. package/examples/simple.js +1 -1
  39. package/examples/simple.mjs +1 -1
  40. package/examples/typescript-server.ts +1 -1
  41. package/examples/use-plugin.js +1 -1
  42. package/fastify.d.ts +34 -22
  43. package/fastify.js +40 -36
  44. package/lib/configValidator.js +902 -1023
  45. package/lib/contentTypeParser.js +6 -16
  46. package/lib/context.js +36 -10
  47. package/lib/decorate.js +3 -1
  48. package/lib/error-handler.js +158 -0
  49. package/lib/error-serializer.js +257 -0
  50. package/lib/errors.js +51 -9
  51. package/lib/fourOhFour.js +31 -20
  52. package/lib/handleRequest.js +10 -13
  53. package/lib/hooks.js +14 -9
  54. package/lib/pluginOverride.js +0 -3
  55. package/lib/pluginUtils.js +3 -2
  56. package/lib/reply.js +121 -175
  57. package/lib/request.js +13 -10
  58. package/lib/route.js +131 -138
  59. package/lib/schema-controller.js +2 -2
  60. package/lib/schemas.js +27 -1
  61. package/lib/server.js +242 -116
  62. package/lib/symbols.js +5 -3
  63. package/lib/validation.js +11 -9
  64. package/lib/warnings.js +4 -12
  65. package/lib/wrapThenable.js +4 -11
  66. package/package.json +37 -39
  67. package/test/404s.test.js +258 -125
  68. package/test/500s.test.js +3 -3
  69. package/test/als.test.js +1 -1
  70. package/test/async-await.test.js +20 -76
  71. package/test/bodyLimit.test.js +1 -1
  72. package/test/build-certificate.js +6 -7
  73. package/test/case-insensitive.test.js +4 -4
  74. package/test/close-pipelining.test.js +2 -2
  75. package/test/close.test.js +11 -11
  76. package/test/content-parser.test.js +32 -0
  77. package/test/context-config.test.js +52 -0
  78. package/test/custom-http-server.test.js +14 -7
  79. package/test/custom-parser-async.test.js +1 -66
  80. package/test/custom-parser.test.js +92 -159
  81. package/test/custom-querystring-parser.test.js +3 -3
  82. package/test/decorator.test.js +11 -13
  83. package/test/delete.test.js +6 -6
  84. package/test/encapsulated-error-handler.test.js +50 -0
  85. package/test/esm/index.test.js +0 -14
  86. package/test/fastify-instance.test.js +4 -4
  87. package/test/fluent-schema.test.js +4 -4
  88. package/test/genReqId.test.js +1 -1
  89. package/test/get.test.js +4 -4
  90. package/test/handler-context.test.js +2 -2
  91. package/test/head.test.js +1 -1
  92. package/test/helper.js +19 -4
  93. package/test/hooks-async.test.js +15 -48
  94. package/test/hooks.on-ready.test.js +10 -5
  95. package/test/hooks.test.js +78 -119
  96. package/test/http2/closing.test.js +10 -16
  97. package/test/http2/constraint.test.js +1 -1
  98. package/test/http2/head.test.js +1 -1
  99. package/test/http2/plain.test.js +1 -1
  100. package/test/http2/secure-with-fallback.test.js +1 -1
  101. package/test/http2/secure.test.js +1 -1
  102. package/test/http2/unknown-http-method.test.js +4 -10
  103. package/test/https/custom-https-server.test.js +12 -6
  104. package/test/https/https.test.js +1 -1
  105. package/test/input-validation.js +3 -3
  106. package/test/internals/handleRequest.test.js +6 -43
  107. package/test/internals/initialConfig.test.js +41 -12
  108. package/test/internals/logger.test.js +2 -2
  109. package/test/internals/reply.test.js +317 -48
  110. package/test/internals/request.test.js +13 -7
  111. package/test/internals/server.test.js +88 -0
  112. package/test/listen.deprecated.test.js +202 -0
  113. package/test/listen.test.js +140 -145
  114. package/test/logger.test.js +82 -42
  115. package/test/maxRequestsPerSocket.test.js +8 -6
  116. package/test/middleware.test.js +2 -25
  117. package/test/nullable-validation.test.js +53 -16
  118. package/test/output-validation.test.js +1 -1
  119. package/test/plugin.test.js +47 -21
  120. package/test/pretty-print.test.js +22 -10
  121. package/test/promises.test.js +1 -1
  122. package/test/proto-poisoning.test.js +6 -6
  123. package/test/register.test.js +3 -3
  124. package/test/reply-error.test.js +126 -15
  125. package/test/reply-trailers.test.js +270 -0
  126. package/test/request-error.test.js +3 -6
  127. package/test/route-hooks.test.js +18 -18
  128. package/test/route-prefix.test.js +2 -1
  129. package/test/route.test.js +206 -22
  130. package/test/router-options.test.js +2 -2
  131. package/test/schema-examples.test.js +11 -5
  132. package/test/schema-feature.test.js +25 -20
  133. package/test/schema-serialization.test.js +9 -9
  134. package/test/schema-special-usage.test.js +5 -153
  135. package/test/schema-validation.test.js +9 -9
  136. package/test/skip-reply-send.test.js +2 -2
  137. package/test/stream.test.js +82 -23
  138. package/test/throw.test.js +8 -5
  139. package/test/trust-proxy.test.js +6 -6
  140. package/test/type-provider.test.js +20 -0
  141. package/test/types/fastify.test-d.ts +10 -18
  142. package/test/types/hooks.test-d.ts +61 -5
  143. package/test/types/import.js +2 -0
  144. package/test/types/import.ts +1 -0
  145. package/test/types/instance.test-d.ts +68 -17
  146. package/test/types/logger.test-d.ts +44 -15
  147. package/test/types/reply.test-d.ts +2 -1
  148. package/test/types/request.test-d.ts +71 -1
  149. package/test/types/route.test-d.ts +8 -2
  150. package/test/types/schema.test-d.ts +2 -39
  151. package/test/types/type-provider.test-d.ts +424 -0
  152. package/test/url-rewriting.test.js +3 -3
  153. package/test/validation-error-handling.test.js +8 -8
  154. package/test/versioned-routes.test.js +30 -18
  155. package/test/wrapThenable.test.js +7 -6
  156. package/types/content-type-parser.d.ts +17 -8
  157. package/types/hooks.d.ts +182 -85
  158. package/types/instance.d.ts +286 -118
  159. package/types/logger.d.ts +18 -104
  160. package/types/plugin.d.ts +10 -4
  161. package/types/reply.d.ts +18 -12
  162. package/types/request.d.ts +13 -8
  163. package/types/route.d.ts +62 -34
  164. package/types/schema.d.ts +1 -1
  165. package/types/type-provider.d.ts +99 -0
  166. package/types/utils.d.ts +1 -1
  167. package/lib/schema-compilers.js +0 -12
  168. package/test/emit-warning.test.js +0 -166
package/lib/fourOhFour.js CHANGED
@@ -9,21 +9,17 @@ const {
9
9
  kRoutePrefix,
10
10
  kCanSetNotFoundHandler,
11
11
  kFourOhFourLevelInstance,
12
- kReply,
13
- kRequest,
14
- kContentTypeParser,
15
- kBodyLimit,
16
- kLogLevel,
17
12
  kFourOhFourContext,
18
- kHooks,
19
- kErrorHandler
13
+ kHooks
20
14
  } = require('./symbols.js')
21
15
  const { lifecycleHooks } = require('./hooks')
16
+ const { buildErrorHandler } = require('./error-handler.js')
22
17
  const fourOhFourContext = {
23
18
  config: {
24
19
  },
25
20
  onSend: [],
26
- onError: []
21
+ onError: [],
22
+ errorHandler: buildErrorHandler()
27
23
  }
28
24
 
29
25
  /**
@@ -34,10 +30,10 @@ const fourOhFourContext = {
34
30
  * kFourOhFourContext: the context in the reply object where the handler will be executed
35
31
  */
36
32
  function fourOhFour (options) {
37
- const { logger, genReqId } = options
33
+ const { logger, genReqId, disableRequestLogging } = options
38
34
 
39
35
  // 404 router, used for handling encapsulated 404 handlers
40
- const router = FindMyWay({ defaultRoute: fourOhFourFallBack })
36
+ const router = FindMyWay({ onBadUrl, defaultRoute: fourOhFourFallBack })
41
37
 
42
38
  return { router, setNotFoundHandler, setContext, arrange404 }
43
39
 
@@ -58,6 +54,26 @@ function fourOhFour (options) {
58
54
  })
59
55
  }
60
56
 
57
+ function onBadUrl (path, req, res) {
58
+ const { url, method } = req
59
+ const message = `Route ${method}:${url} not found`
60
+ const body = `{"error":"Not Found","message":"${message}","statusCode":404}`
61
+
62
+ // simulate normal route logging
63
+ if (!disableRequestLogging) {
64
+ const id = genReqId(req)
65
+ const childLogger = logger.child({ reqId: id })
66
+ childLogger.info({ req }, 'incoming request')
67
+ childLogger.info({ req }, message)
68
+ }
69
+
70
+ res.writeHead(404, {
71
+ 'Content-Type': 'application/json',
72
+ 'Content-Length': body.length
73
+ })
74
+ res.end(body)
75
+ }
76
+
61
77
  function setContext (instance, context) {
62
78
  const _404Context = Object.assign({}, instance[kFourOhFourContext])
63
79
  _404Context.onSend = context.onSend
@@ -118,17 +134,12 @@ function fourOhFour (options) {
118
134
  }
119
135
 
120
136
  function _setNotFoundHandler (prefix, opts, handler, avvio, routeHandler) {
121
- const context = new Context(
122
- opts.schema,
137
+ const context = new Context({
138
+ schema: opts.schema,
123
139
  handler,
124
- this[kReply],
125
- this[kRequest],
126
- this[kContentTypeParser],
127
- opts.config || {},
128
- this[kErrorHandler],
129
- this[kBodyLimit],
130
- this[kLogLevel]
131
- )
140
+ config: opts.config || {},
141
+ server: this
142
+ })
132
143
 
133
144
  avvio.once('preReady', () => {
134
145
  const context = this[kFourOhFourContext]
@@ -3,12 +3,14 @@
3
3
  const { validate: validateSchema } = require('./validation')
4
4
  const { hookRunner, hookIterator } = require('./hooks')
5
5
  const wrapThenable = require('./wrapThenable')
6
-
7
- const { kReplyIsError } = require('./symbols')
6
+ const {
7
+ kReplyIsError
8
+ } = require('./symbols')
8
9
 
9
10
  function handleRequest (err, request, reply) {
10
11
  if (reply.sent === true) return
11
12
  if (err != null) {
13
+ reply[kReplyIsError] = true
12
14
  reply.send(err)
13
15
  return
14
16
  }
@@ -55,7 +57,7 @@ function handleRequest (err, request, reply) {
55
57
  }
56
58
 
57
59
  // Return 404 instead of 405 see https://github.com/fastify/fastify/pull/862 for discussion
58
- reply.code(404).send(new Error('Not Found'))
60
+ handler(request, reply)
59
61
  }
60
62
 
61
63
  function handler (request, reply) {
@@ -77,11 +79,10 @@ function handler (request, reply) {
77
79
  }
78
80
 
79
81
  function preValidationCallback (err, request, reply) {
80
- if (reply.sent === true ||
81
- reply.raw.writableEnded === true ||
82
- reply.raw.writable === false) return
82
+ if (reply.sent === true) return
83
83
 
84
84
  if (err != null) {
85
+ reply[kReplyIsError] = true
85
86
  reply.send(err)
86
87
  return
87
88
  }
@@ -111,11 +112,10 @@ function preValidationCallback (err, request, reply) {
111
112
  }
112
113
 
113
114
  function preHandlerCallback (err, request, reply) {
114
- if (reply.sent ||
115
- reply.raw.writableEnded === true ||
116
- reply.raw.writable === false) return
115
+ if (reply.sent) return
117
116
 
118
117
  if (err != null) {
118
+ reply[kReplyIsError] = true
119
119
  reply.send(err)
120
120
  return
121
121
  }
@@ -125,10 +125,7 @@ function preHandlerCallback (err, request, reply) {
125
125
  try {
126
126
  result = reply.context.handler(request, reply)
127
127
  } catch (err) {
128
- if (!(err instanceof Error)) {
129
- reply[kReplyIsError] = true
130
- }
131
-
128
+ reply[kReplyIsError] = true
132
129
  reply.send(err)
133
130
  return
134
131
  }
package/lib/hooks.js CHANGED
@@ -21,11 +21,13 @@ const supportedHooks = lifecycleHooks.concat(applicationHooks)
21
21
  const {
22
22
  FST_ERR_HOOK_INVALID_TYPE,
23
23
  FST_ERR_HOOK_INVALID_HANDLER,
24
- FST_ERR_SEND_UNDEFINED_ERR
24
+ FST_ERR_SEND_UNDEFINED_ERR,
25
+ FST_ERR_HOOK_TIMEOUT,
26
+ AVVIO_ERRORS_MAP,
27
+ appendStackTrace
25
28
  } = require('./errors')
26
29
 
27
30
  const {
28
- kReplyIsError,
29
31
  kChildren,
30
32
  kHooks
31
33
  } = require('./symbols')
@@ -84,6 +86,14 @@ function hookRunnerApplication (hookName, boot, server, cb) {
84
86
 
85
87
  function exit (err) {
86
88
  if (err) {
89
+ if (err.code === 'AVV_ERR_READY_TIMEOUT') {
90
+ err = appendStackTrace(err, new FST_ERR_HOOK_TIMEOUT(hookName))
91
+ } else {
92
+ err = AVVIO_ERRORS_MAP[err.code] != null
93
+ ? appendStackTrace(err, new AVVIO_ERRORS_MAP[err.code](err.message))
94
+ : err
95
+ }
96
+
87
97
  cb(err)
88
98
  return
89
99
  }
@@ -178,9 +188,8 @@ function hookRunner (functions, runner, request, reply, cb) {
178
188
  function handleReject (err) {
179
189
  if (!err) {
180
190
  err = new FST_ERR_SEND_UNDEFINED_ERR()
181
- } else if (!(err instanceof Error)) {
182
- reply[kReplyIsError] = true
183
191
  }
192
+
184
193
  cb(err, request, reply)
185
194
  }
186
195
 
@@ -201,11 +210,7 @@ function onSendHookRunner (functions, request, reply, payload, cb) {
201
210
  }
202
211
 
203
212
  if (i === functions.length) {
204
- try {
205
- cb(null, request, reply, payload)
206
- } catch (err) {
207
- handleReject(err)
208
- }
213
+ cb(null, request, reply, payload)
209
214
  return
210
215
  }
211
216
 
@@ -39,10 +39,7 @@ module.exports = function override (old, fn, opts) {
39
39
  instance[kChildren] = []
40
40
 
41
41
  instance[kReply] = Reply.buildReply(instance[kReply])
42
- instance[kReply].prototype.server = instance
43
-
44
42
  instance[kRequest] = Request.buildRequest(instance[kRequest])
45
- instance[kRequest].prototype.server = instance
46
43
 
47
44
  instance[kContentTypeParser] = ContentTypeParser.helpers.buildContentTypeParser(instance[kContentTypeParser])
48
45
  instance[kHooks] = buildHooks(instance[kHooks])
@@ -102,9 +102,10 @@ function checkVersion (fn) {
102
102
  if (!meta) return
103
103
 
104
104
  const requiredVersion = meta.fastify
105
- if (!requiredVersion) return
106
105
 
107
- if (!semver.satisfies(this.version, requiredVersion)) throw new FST_ERR_PLUGIN_VERSION_MISMATCH(meta.name, requiredVersion, this.version)
106
+ if (requiredVersion && !semver.satisfies(this.version, requiredVersion)) {
107
+ throw new FST_ERR_PLUGIN_VERSION_MISMATCH(meta.name, requiredVersion, this.version)
108
+ }
108
109
  }
109
110
 
110
111
  function registerPluginName (fn) {