fastify 4.26.0 → 4.26.2
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.
- package/docs/Guides/Database.md +2 -0
- package/docs/Guides/Ecosystem.md +4 -0
- package/docs/Guides/Serverless.md +111 -1
- package/docs/Reference/Errors.md +2 -0
- package/docs/Reference/TypeScript.md +1 -1
- package/docs/Reference/Warnings.md +15 -2
- package/fastify.d.ts +3 -3
- package/fastify.js +7 -2
- package/lib/contentTypeParser.js +1 -1
- package/lib/error-serializer.js +28 -29
- package/lib/errors.js +8 -1
- package/lib/warnings.js +1 -1
- package/package.json +2 -2
- package/test/hooks.on-ready.test.js +1 -1
- package/test/internals/errors.test.js +17 -7
- package/test/plugin.4.test.js +3 -3
- package/test/pretty-print.test.js +1 -1
- package/test/set-error-handler.test.js +13 -0
- package/test/types/fastify.test-d.ts +1 -1
- package/test/types/hooks.test-d.ts +4 -1
- package/test/types/import.js +2 -0
- package/test/types/request.test-d.ts +1 -1
- package/types/request.d.ts +5 -4
- package/.vscode/settings.json +0 -22
package/docs/Guides/Database.md
CHANGED
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -386,6 +386,8 @@ section.
|
|
|
386
386
|
Providers.
|
|
387
387
|
- [`fastify-guard`](https://github.com/hsynlms/fastify-guard) A Fastify plugin
|
|
388
388
|
that protects endpoints by checking authenticated user roles and/or scopes.
|
|
389
|
+
- [`fastify-hana`](https://github.com/yoav0gal/fastify-hana) connects your
|
|
390
|
+
application to [`SAP-HANA`](https://help.sap.com/docs/SAP_HANA_CLIENT).
|
|
389
391
|
- [`fastify-hashids`](https://github.com/andersonjoseph/fastify-hashids) A Fastify
|
|
390
392
|
plugin to encode/decode IDs using [hashids](https://github.com/niieani/hashids.js).
|
|
391
393
|
- [`fastify-hasura`](https://github.com/ManUtopiK/fastify-hasura) A Fastify
|
|
@@ -527,6 +529,8 @@ middlewares into Fastify plugins
|
|
|
527
529
|
across every part of your server.
|
|
528
530
|
- [`fastify-osm`](https://github.com/gzileni/fastify-osm) Fastify
|
|
529
531
|
OSM plugin to run overpass queries by OpenStreetMap.
|
|
532
|
+
- [`fastify-override`](https://github.com/matthyk/fastify-override)
|
|
533
|
+
Fastify plugin to override decorators, plugins and hooks for testing purposes
|
|
530
534
|
- [`fastify-peekaboo`](https://github.com/simone-sanfratello/fastify-peekaboo)
|
|
531
535
|
Fastify plugin for memoize responses by expressive settings.
|
|
532
536
|
- [`fastify-piscina`](https://github.com/piscinajs/fastify-piscina) A worker
|
|
@@ -26,6 +26,7 @@ snippet of code.
|
|
|
26
26
|
|
|
27
27
|
- [AWS](#aws)
|
|
28
28
|
- [Google Cloud Functions](#google-cloud-functions)
|
|
29
|
+
- [Google Firebase Functions](#google-firebase-functions)
|
|
29
30
|
- [Google Cloud Run](#google-cloud-run)
|
|
30
31
|
- [Netlify Lambda](#netlify-lambda)
|
|
31
32
|
- [Platformatic Cloud](#platformatic-cloud)
|
|
@@ -203,7 +204,7 @@ const fastifyFunction = async (request, reply) => {
|
|
|
203
204
|
fastify.server.emit('request', request, reply)
|
|
204
205
|
}
|
|
205
206
|
|
|
206
|
-
|
|
207
|
+
exports.fastifyFunction = fastifyFunction;
|
|
207
208
|
```
|
|
208
209
|
|
|
209
210
|
### Local test
|
|
@@ -260,6 +261,115 @@ curl -X POST https://$GOOGLE_REGION-$GOOGLE_PROJECT.cloudfunctions.net/me \
|
|
|
260
261
|
- [Google Cloud Functions - Node.js Quickstart
|
|
261
262
|
](https://cloud.google.com/functions/docs/quickstart-nodejs)
|
|
262
263
|
|
|
264
|
+
## Google Firebase Functions
|
|
265
|
+
|
|
266
|
+
Follow this guide if you want to use Fastify as the HTTP framework for
|
|
267
|
+
Firebase Functions instead of the vanilla JavaScript router provided with
|
|
268
|
+
`onRequest(async (req, res) => {}`.
|
|
269
|
+
|
|
270
|
+
### The onRequest() handler
|
|
271
|
+
|
|
272
|
+
We use the `onRequest` function to wrap our Fastify application instance.
|
|
273
|
+
|
|
274
|
+
As such, we'll begin with importing it to the code:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
const { onRequest } = require("firebase-functions/v2/https")
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Creation of Fastify instance
|
|
281
|
+
|
|
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
|
|
284
|
+
plugins, hooks and other settings. As follows:
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
const fastify = require("fastify")({
|
|
288
|
+
logger: true,
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
const fastifyApp = async (request, reply) => {
|
|
292
|
+
await registerRoutes(fastify)
|
|
293
|
+
await fastify.ready()
|
|
294
|
+
fastify.server.emit("request", request, reply)
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Add Custom `contentTypeParser` to Fastify instance and define endpoints
|
|
299
|
+
|
|
300
|
+
Firebase Function's HTTP layer already parses the request
|
|
301
|
+
and makes a JSON payload available. It also provides access
|
|
302
|
+
to the raw body, unparsed, which is useful in order to calculate
|
|
303
|
+
request signatures to validate HTTP webhooks.
|
|
304
|
+
|
|
305
|
+
Add as follows to the `registerRoutes()` function:
|
|
306
|
+
|
|
307
|
+
```js
|
|
308
|
+
async function registerRoutes (fastify) {
|
|
309
|
+
fastify.addContentTypeParser("application/json", {}, (req, payload, done) => {
|
|
310
|
+
// useful to include the request's raw body on the `req` object that will
|
|
311
|
+
// later be available in your other routes so you can calculate the HMAC
|
|
312
|
+
// if needed
|
|
313
|
+
req.rawBody = payload.rawBody
|
|
314
|
+
|
|
315
|
+
// payload.body is already the parsed JSON so we just fire the done callback
|
|
316
|
+
// with it
|
|
317
|
+
done(null, payload.body)
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
// define your endpoints here...
|
|
321
|
+
fastify.post("/some-route-here", async (request, reply) => {}
|
|
322
|
+
|
|
323
|
+
fastify.get('/', async (request, reply) => {
|
|
324
|
+
reply.send({message: 'Hello World!'})
|
|
325
|
+
})
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Export the function using Firebase onRequest
|
|
330
|
+
|
|
331
|
+
Final step is to export the Fastify app instance to Firebase's own
|
|
332
|
+
`onRequest()` function so it can pass the request and reply objects to it:
|
|
333
|
+
|
|
334
|
+
```js
|
|
335
|
+
exports.app = onRequest(fastifyApp)
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Local test
|
|
339
|
+
|
|
340
|
+
Install the Firebase tools functions so you can use the CLI:
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
npm i -g firebase-tools
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Then you can run your function locally with:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
firebase emulators:start --only functions
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Deploy
|
|
353
|
+
|
|
354
|
+
Deploy your Firebase Functions with:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
firebase deploy --only functions
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### Read logs
|
|
361
|
+
|
|
362
|
+
Use the Firebase tools CLI:
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
firebase functions:log
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### References
|
|
369
|
+
- [Fastify on Firebase Functions](https://github.com/lirantal/lemon-squeezy-firebase-webhook-fastify/blob/main/package.json)
|
|
370
|
+
- [An article about HTTP webhooks on Firebase Functions and Fastify: A Practical Case Study with Lemon Squeezy](https://lirantal.com/blog/http-webhooks-firebase-functions-fastify-practical-case-study-lemon-squeezy)
|
|
371
|
+
|
|
372
|
+
|
|
263
373
|
## Google Cloud Run
|
|
264
374
|
|
|
265
375
|
Unlike AWS Lambda or Google Cloud Functions, Google Cloud Run is a serverless
|
package/docs/Reference/Errors.md
CHANGED
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
- [FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE](#fst_err_plugin_not_present_in_instance)
|
|
93
93
|
- [FST_ERR_VALIDATION](#fst_err_validation)
|
|
94
94
|
- [FST_ERR_LISTEN_OPTIONS_INVALID](#fst_err_listen_options_invalid)
|
|
95
|
+
- [FST_ERR_ERROR_HANDLER_NOT_FN](#fst_err_error_handler_not_fn)
|
|
95
96
|
|
|
96
97
|
### Error Handling In Node.js
|
|
97
98
|
<a id="error-handling"></a>
|
|
@@ -361,4 +362,5 @@ but the body is being consumed. | Make sure you don't consume the `Response.body
|
|
|
361
362
|
| <a id="fst_err_plugin_not_present_in_instance">FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE</a> | The decorator is not present in the instance. | - | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
|
362
363
|
| <a id="fst_err_validation">FST_ERR_VALIDATION</a> | The Request failed the payload validation. | Check the request payload. | [#4824](https://github.com/fastify/fastify/pull/4824) |
|
|
363
364
|
| <a id="fst_err_listen_options_invalid">FST_ERR_LISTEN_OPTIONS_INVALID</a> | Invalid listen options. | Check the listen options. | [#4886](https://github.com/fastify/fastify/pull/4886) |
|
|
365
|
+
| <a id="fst_err_error_handler_not_fn">FST_ERR_ERROR_HANDLER_NOT_FN</a> | Error Handler must be a function | Provide a function to `setErrorHandler`. | [#5317](https://github.com/fastify/fastify/pull/5317) |
|
|
364
366
|
|
|
@@ -1093,7 +1093,7 @@ server.get<requestGeneric>('/', async (request, reply) => {
|
|
|
1093
1093
|
```
|
|
1094
1094
|
|
|
1095
1095
|
If you want to see a detailed example of using this interface check out the
|
|
1096
|
-
Learn by Example section: [JSON Schema](#
|
|
1096
|
+
Learn by Example section: [JSON Schema](#json-schema).
|
|
1097
1097
|
|
|
1098
1098
|
##### fastify.RawRequestDefaultExpression\<[RawServer][RawServerGeneric]\>
|
|
1099
1099
|
[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L23)
|
|
@@ -29,8 +29,21 @@
|
|
|
29
29
|
## Warnings
|
|
30
30
|
|
|
31
31
|
### Warnings In Fastify
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
|
|
33
|
+
Fastify utilizes Node.js's [warning event](https://nodejs.org/api/process.html#event-warning)
|
|
34
|
+
API to notify users of deprecated features and known coding mistakes. Fastify's
|
|
35
|
+
warnings are recognizable by the `FSTWRN` and `FSTDEP` prefixes on warning
|
|
36
|
+
code. When encountering such a warning, it is highly recommended that the
|
|
37
|
+
cause of the warning be determined through use of the
|
|
38
|
+
[`--trace-warnings`](https://nodejs.org/api/cli.html#--trace-warnings) and
|
|
39
|
+
[`--trace-deprecation`](https://nodejs.org/api/cli.html#--trace-deprecation)
|
|
40
|
+
flags. These will produce stack traces pointing out where the issue occurs
|
|
41
|
+
in the application's code. Issues opened about warnings without including
|
|
42
|
+
this information may be closed due to lack of information.
|
|
43
|
+
|
|
44
|
+
In addition to tracing, warnings can also be disabled. It is not recommended to
|
|
45
|
+
disable warnings as a matter of course, but if necessary, they can be disabled
|
|
46
|
+
by using any of the following methods:
|
|
34
47
|
|
|
35
48
|
- setting the `NODE_NO_WARNINGS` environment variable to `1`
|
|
36
49
|
- passing the `--no-warnings` flag to the node process
|
package/fastify.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { Chain as LightMyRequestChain, InjectOptions, Response as LightMyRequest
|
|
|
12
12
|
import { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction } from './types/content-type-parser'
|
|
13
13
|
import { FastifyRequestContext, FastifyContextConfig, FastifyReplyContext } from './types/context'
|
|
14
14
|
import { FastifyErrorCodes } from './types/errors'
|
|
15
|
-
import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onListenAsyncHookHandler, onListenHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler } from './types/hooks'
|
|
15
|
+
import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onListenAsyncHookHandler, onListenHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler, preCloseAsyncHookHandler, preCloseHookHandler } from './types/hooks'
|
|
16
16
|
import { FastifyListenOptions, FastifyInstance, PrintRoutesOptions } from './types/instance'
|
|
17
17
|
import { FastifyBaseLogger, FastifyLoggerInstance, FastifyLoggerOptions, PinoLoggerOptions, FastifyLogFn, LogLevel } from './types/logger'
|
|
18
18
|
import { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, FastifyPlugin } from './types/plugin'
|
|
@@ -152,7 +152,7 @@ declare namespace fastify {
|
|
|
152
152
|
) => void,
|
|
153
153
|
rewriteUrl?: (
|
|
154
154
|
// The RawRequestDefaultExpression, RawReplyDefaultExpression, and FastifyTypeProviderDefault parameters
|
|
155
|
-
// should be narrowed further but those generic parameters are not passed to this FastifyServerOptions type
|
|
155
|
+
// should be narrowed further but those generic parameters are not passed to this FastifyServerOptions type
|
|
156
156
|
this: FastifyInstance<RawServer, RawRequestDefaultExpression<RawServer>, RawReplyDefaultExpression<RawServer>, Logger, FastifyTypeProviderDefault>,
|
|
157
157
|
req: RawRequestDefaultExpression<RawServer>
|
|
158
158
|
) => string,
|
|
@@ -183,7 +183,7 @@ declare namespace fastify {
|
|
|
183
183
|
FastifyError, // '@fastify/error'
|
|
184
184
|
FastifySchema, FastifySchemaCompiler, // './types/schema'
|
|
185
185
|
HTTPMethods, RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault, ContextConfigDefault, RequestBodyDefault, RequestQuerystringDefault, RequestParamsDefault, RequestHeadersDefault, // './types/utils'
|
|
186
|
-
DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onListenAsyncHookHandler, onListenHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler, // './types/hooks'
|
|
186
|
+
DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, onCloseAsyncHookHandler, onCloseHookHandler, onErrorAsyncHookHandler, onErrorHookHandler, onReadyAsyncHookHandler, onReadyHookHandler, onListenAsyncHookHandler, onListenHookHandler, onRegisterHookHandler, onRequestAsyncHookHandler, onRequestHookHandler, onResponseAsyncHookHandler, onResponseHookHandler, onRouteHookHandler, onSendAsyncHookHandler, onSendHookHandler, onTimeoutAsyncHookHandler, onTimeoutHookHandler, preHandlerAsyncHookHandler, preHandlerHookHandler, preParsingAsyncHookHandler, preParsingHookHandler, preSerializationAsyncHookHandler, preSerializationHookHandler, preValidationAsyncHookHandler, preValidationHookHandler, onRequestAbortHookHandler, onRequestAbortAsyncHookHandler, preCloseAsyncHookHandler, preCloseHookHandler, // './types/hooks'
|
|
187
187
|
FastifyServerFactory, FastifyServerFactoryHandler, // './types/serverFactory'
|
|
188
188
|
FastifyTypeProvider, FastifyTypeProviderDefault, // './types/type-provider'
|
|
189
189
|
FastifyErrorCodes, // './types/errors'
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.26.
|
|
3
|
+
const VERSION = '4.26.2'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('node:http')
|
|
@@ -71,7 +71,8 @@ const {
|
|
|
71
71
|
FST_ERR_INSTANCE_ALREADY_LISTENING,
|
|
72
72
|
FST_ERR_REOPENED_CLOSE_SERVER,
|
|
73
73
|
FST_ERR_ROUTE_REWRITE_NOT_STR,
|
|
74
|
-
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN
|
|
74
|
+
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN,
|
|
75
|
+
FST_ERR_ERROR_HANDLER_NOT_FN
|
|
75
76
|
} = errorCodes
|
|
76
77
|
|
|
77
78
|
const { buildErrorHandler } = require('./lib/error-handler.js')
|
|
@@ -844,6 +845,10 @@ function fastify (options) {
|
|
|
844
845
|
function setErrorHandler (func) {
|
|
845
846
|
throwIfAlreadyStarted('Cannot call "setErrorHandler"!')
|
|
846
847
|
|
|
848
|
+
if (typeof func !== 'function') {
|
|
849
|
+
throw new FST_ERR_ERROR_HANDLER_NOT_FN()
|
|
850
|
+
}
|
|
851
|
+
|
|
847
852
|
this[kErrorHandler] = buildErrorHandler(this[kErrorHandler], func.bind(this))
|
|
848
853
|
return this
|
|
849
854
|
}
|
package/lib/contentTypeParser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { AsyncResource } = require('node:async_hooks')
|
|
4
|
-
const { Fifo } = require('toad-cache')
|
|
4
|
+
const { FifoMap: Fifo } = require('toad-cache')
|
|
5
5
|
const { safeParse: safeParseContentType, defaultContentType } = require('fast-content-type-parse')
|
|
6
6
|
const secureJson = require('secure-json-parse')
|
|
7
7
|
const {
|
package/lib/error-serializer.js
CHANGED
|
@@ -25,35 +25,34 @@
|
|
|
25
25
|
|
|
26
26
|
if (obj === null) return '{}'
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return json + '}'
|
|
28
|
+
let json = '{'
|
|
29
|
+
let addComma = false
|
|
30
|
+
|
|
31
|
+
if (obj["statusCode"] !== undefined) {
|
|
32
|
+
!addComma && (addComma = true) || (json += ',')
|
|
33
|
+
json += "\"statusCode\":"
|
|
34
|
+
json += serializer.asNumber(obj["statusCode"])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (obj["code"] !== undefined) {
|
|
38
|
+
!addComma && (addComma = true) || (json += ',')
|
|
39
|
+
json += "\"code\":"
|
|
40
|
+
json += serializer.asString(obj["code"])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (obj["error"] !== undefined) {
|
|
44
|
+
!addComma && (addComma = true) || (json += ',')
|
|
45
|
+
json += "\"error\":"
|
|
46
|
+
json += serializer.asString(obj["error"])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (obj["message"] !== undefined) {
|
|
50
|
+
!addComma && (addComma = true) || (json += ',')
|
|
51
|
+
json += "\"message\":"
|
|
52
|
+
json += serializer.asString(obj["message"])
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return json + '}'
|
|
57
56
|
|
|
58
57
|
}
|
|
59
58
|
|
package/lib/errors.js
CHANGED
|
@@ -64,6 +64,12 @@ const codes = {
|
|
|
64
64
|
500,
|
|
65
65
|
TypeError
|
|
66
66
|
),
|
|
67
|
+
FST_ERR_ERROR_HANDLER_NOT_FN: createError(
|
|
68
|
+
'FST_ERR_ERROR_HANDLER_NOT_FN',
|
|
69
|
+
'Error Handler must be a function',
|
|
70
|
+
500,
|
|
71
|
+
TypeError
|
|
72
|
+
),
|
|
67
73
|
|
|
68
74
|
/**
|
|
69
75
|
* ContentTypeParser
|
|
@@ -464,5 +470,6 @@ module.exports.AVVIO_ERRORS_MAP = {
|
|
|
464
470
|
AVV_ERR_PLUGIN_NOT_VALID: codes.FST_ERR_PLUGIN_NOT_VALID,
|
|
465
471
|
AVV_ERR_ROOT_PLG_BOOTED: codes.FST_ERR_ROOT_PLG_BOOTED,
|
|
466
472
|
AVV_ERR_PARENT_PLG_LOADED: codes.FST_ERR_PARENT_PLUGIN_BOOTED,
|
|
467
|
-
AVV_ERR_READY_TIMEOUT: codes.FST_ERR_PLUGIN_TIMEOUT
|
|
473
|
+
AVV_ERR_READY_TIMEOUT: codes.FST_ERR_PLUGIN_TIMEOUT,
|
|
474
|
+
AVV_ERR_PLUGIN_EXEC_TIMEOUT: codes.FST_ERR_PLUGIN_TIMEOUT
|
|
468
475
|
}
|
package/lib/warnings.js
CHANGED
|
@@ -79,7 +79,7 @@ const FSTDEP019 = createDeprecation({
|
|
|
79
79
|
|
|
80
80
|
const FSTDEP020 = createDeprecation({
|
|
81
81
|
code: 'FSTDEP020',
|
|
82
|
-
message: 'You are using the deprecated "reply.getResponseTime()"
|
|
82
|
+
message: 'You are using the deprecated "reply.getResponseTime()" method. Use the "reply.elapsedTime" property instead. Method "reply.getResponseTime()" will be removed in `fastify@5`.'
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
const FSTWRN001 = createWarning({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "4.26.
|
|
3
|
+
"version": "4.26.2",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
"@fastify/error": "^3.4.0",
|
|
205
205
|
"@fastify/fast-json-stringify-compiler": "^4.3.0",
|
|
206
206
|
"abstract-logging": "^2.0.1",
|
|
207
|
-
"avvio": "^8.
|
|
207
|
+
"avvio": "^8.3.0",
|
|
208
208
|
"fast-content-type-parse": "^1.1.0",
|
|
209
209
|
"fast-json-stringify": "^5.8.0",
|
|
210
210
|
"find-my-way": "^8.0.0",
|
|
@@ -295,7 +295,7 @@ t.test('onReady cannot add lifecycle hooks', t => {
|
|
|
295
295
|
t.ok(error)
|
|
296
296
|
t.equal(error.message, 'Root plugin has already booted')
|
|
297
297
|
// TODO: look where the error pops up
|
|
298
|
-
t.equal(error.code, '
|
|
298
|
+
t.equal(error.code, 'AVV_ERR_ROOT_PLG_BOOTED')
|
|
299
299
|
done(error)
|
|
300
300
|
}
|
|
301
301
|
})
|
|
@@ -5,7 +5,7 @@ const errors = require('../../lib/errors')
|
|
|
5
5
|
const { readFileSync } = require('node:fs')
|
|
6
6
|
const { resolve } = require('node:path')
|
|
7
7
|
|
|
8
|
-
test('should expose
|
|
8
|
+
test('should expose 80 errors', t => {
|
|
9
9
|
t.plan(1)
|
|
10
10
|
const exportedKeys = Object.keys(errors)
|
|
11
11
|
let counter = 0
|
|
@@ -14,11 +14,11 @@ test('should expose 79 errors', t => {
|
|
|
14
14
|
counter++
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
t.equal(counter,
|
|
17
|
+
t.equal(counter, 80)
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
test('ensure name and codes of Errors are identical', t => {
|
|
21
|
-
t.plan(
|
|
21
|
+
t.plan(80)
|
|
22
22
|
const exportedKeys = Object.keys(errors)
|
|
23
23
|
for (const key of exportedKeys) {
|
|
24
24
|
if (errors[key].name === 'FastifyError') {
|
|
@@ -827,8 +827,18 @@ test('FST_ERR_LISTEN_OPTIONS_INVALID', t => {
|
|
|
827
827
|
t.ok(error instanceof TypeError)
|
|
828
828
|
})
|
|
829
829
|
|
|
830
|
+
test('FST_ERR_ERROR_HANDLER_NOT_FN', t => {
|
|
831
|
+
t.plan(5)
|
|
832
|
+
const error = new errors.FST_ERR_ERROR_HANDLER_NOT_FN()
|
|
833
|
+
t.equal(error.name, 'FastifyError')
|
|
834
|
+
t.equal(error.code, 'FST_ERR_ERROR_HANDLER_NOT_FN')
|
|
835
|
+
t.equal(error.message, 'Error Handler must be a function')
|
|
836
|
+
t.equal(error.statusCode, 500)
|
|
837
|
+
t.ok(error instanceof TypeError)
|
|
838
|
+
})
|
|
839
|
+
|
|
830
840
|
test('Ensure that all errors are in Errors.md TOC', t => {
|
|
831
|
-
t.plan(
|
|
841
|
+
t.plan(80)
|
|
832
842
|
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
833
843
|
|
|
834
844
|
const exportedKeys = Object.keys(errors)
|
|
@@ -840,7 +850,7 @@ test('Ensure that all errors are in Errors.md TOC', t => {
|
|
|
840
850
|
})
|
|
841
851
|
|
|
842
852
|
test('Ensure that non-existing errors are not in Errors.md TOC', t => {
|
|
843
|
-
t.plan(
|
|
853
|
+
t.plan(80)
|
|
844
854
|
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
845
855
|
|
|
846
856
|
const matchRE = / {4}- \[([A-Z0-9_]+)\]\(#[a-z0-9_]+\)/g
|
|
@@ -853,7 +863,7 @@ test('Ensure that non-existing errors are not in Errors.md TOC', t => {
|
|
|
853
863
|
})
|
|
854
864
|
|
|
855
865
|
test('Ensure that all errors are in Errors.md documented', t => {
|
|
856
|
-
t.plan(
|
|
866
|
+
t.plan(80)
|
|
857
867
|
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
858
868
|
|
|
859
869
|
const exportedKeys = Object.keys(errors)
|
|
@@ -865,7 +875,7 @@ test('Ensure that all errors are in Errors.md documented', t => {
|
|
|
865
875
|
})
|
|
866
876
|
|
|
867
877
|
test('Ensure that non-existing errors are not in Errors.md documented', t => {
|
|
868
|
-
t.plan(
|
|
878
|
+
t.plan(80)
|
|
869
879
|
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
870
880
|
|
|
871
881
|
const matchRE = /<a id="[0-9a-zA-Z_]+">([0-9a-zA-Z_]+)<\/a>/g
|
package/test/plugin.4.test.js
CHANGED
|
@@ -22,7 +22,7 @@ test('pluginTimeout', t => {
|
|
|
22
22
|
"fastify-plugin: Plugin did not start in time: 'function (app, opts, done) { -- // to no call done on purpose'. You may have forgotten to call 'done' function or to resolve a Promise")
|
|
23
23
|
t.equal(err.code, 'FST_ERR_PLUGIN_TIMEOUT')
|
|
24
24
|
t.ok(err.cause)
|
|
25
|
-
t.equal(err.cause.code, '
|
|
25
|
+
t.equal(err.cause.code, 'AVV_ERR_PLUGIN_EXEC_TIMEOUT')
|
|
26
26
|
})
|
|
27
27
|
})
|
|
28
28
|
|
|
@@ -40,7 +40,7 @@ test('pluginTimeout - named function', t => {
|
|
|
40
40
|
"fastify-plugin: Plugin did not start in time: 'nameFunction'. You may have forgotten to call 'done' function or to resolve a Promise")
|
|
41
41
|
t.equal(err.code, 'FST_ERR_PLUGIN_TIMEOUT')
|
|
42
42
|
t.ok(err.cause)
|
|
43
|
-
t.equal(err.cause.code, '
|
|
43
|
+
t.equal(err.cause.code, 'AVV_ERR_PLUGIN_EXEC_TIMEOUT')
|
|
44
44
|
})
|
|
45
45
|
})
|
|
46
46
|
|
|
@@ -60,7 +60,7 @@ test('pluginTimeout default', t => {
|
|
|
60
60
|
"fastify-plugin: Plugin did not start in time: 'function (app, opts, done) { -- // default time elapsed without calling done'. You may have forgotten to call 'done' function or to resolve a Promise")
|
|
61
61
|
t.equal(err.code, 'FST_ERR_PLUGIN_TIMEOUT')
|
|
62
62
|
t.ok(err.cause)
|
|
63
|
-
t.equal(err.cause.code, '
|
|
63
|
+
t.equal(err.cause.code, 'AVV_ERR_PLUGIN_EXEC_TIMEOUT')
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
t.teardown(clock.uninstall)
|
|
@@ -220,7 +220,7 @@ test('pretty print - empty plugins', t => {
|
|
|
220
220
|
fastify.ready(() => {
|
|
221
221
|
const tree = fastify.printPlugins()
|
|
222
222
|
t.equal(typeof tree, 'string')
|
|
223
|
-
t.match(tree,
|
|
223
|
+
t.match(tree, /root \d+ ms\n└── bound _after \d+ ms/m)
|
|
224
224
|
})
|
|
225
225
|
})
|
|
226
226
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const Fastify = require('..')
|
|
6
|
+
const { FST_ERR_ERROR_HANDLER_NOT_FN } = require('../lib/errors')
|
|
7
|
+
|
|
8
|
+
test('setErrorHandler should throw an error if the handler is not a function', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
const fastify = Fastify()
|
|
11
|
+
|
|
12
|
+
t.throws(() => fastify.setErrorHandler('not a function'), new FST_ERR_ERROR_HANDLER_NOT_FN())
|
|
13
|
+
})
|
|
@@ -57,7 +57,7 @@ expectAssignable<InjectOptions>({ query: '' })
|
|
|
57
57
|
fastify({ http2: true, https: {} }).inject().then((resp) => {
|
|
58
58
|
expectAssignable<LightMyRequestResponse>(resp)
|
|
59
59
|
})
|
|
60
|
-
const lightMyRequestCallback: LightMyRequestCallback = (err: Error, response: LightMyRequestResponse) => {
|
|
60
|
+
const lightMyRequestCallback: LightMyRequestCallback = (err: Error | undefined, response: LightMyRequestResponse | undefined) => {
|
|
61
61
|
if (err) throw err
|
|
62
62
|
}
|
|
63
63
|
fastify({ http2: true, https: {} }).inject({}, lightMyRequestCallback)
|
|
@@ -12,7 +12,10 @@ import fastify, {
|
|
|
12
12
|
RawRequestDefaultExpression,
|
|
13
13
|
RawServerDefault,
|
|
14
14
|
RegisterOptions,
|
|
15
|
-
RouteOptions
|
|
15
|
+
RouteOptions,
|
|
16
|
+
// preClose hook types should be exported correctly https://github.com/fastify/fastify/pull/5335
|
|
17
|
+
preCloseAsyncHookHandler,
|
|
18
|
+
preCloseHookHandler
|
|
16
19
|
} from '../../fastify'
|
|
17
20
|
import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, preHandlerAsyncHookHandler } from '../../types/hooks'
|
|
18
21
|
import { FastifyRouteConfig, RouteGenericInterface } from '../../types/route'
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import pino from 'pino'
|
|
2
1
|
import { expectAssignable, expectType } from 'tsd'
|
|
3
2
|
import fastify, {
|
|
4
3
|
ContextConfigDefault,
|
|
@@ -83,6 +82,7 @@ const getHandler: RouteHandler = function (request, _reply) {
|
|
|
83
82
|
expectType<FastifySchema>(request.routeSchema)
|
|
84
83
|
expectType<FastifySchema>(request.routeOptions.schema)
|
|
85
84
|
expectType<RouteHandlerMethod>(request.routeOptions.handler)
|
|
85
|
+
expectType<string | undefined>(request.routeOptions.url)
|
|
86
86
|
|
|
87
87
|
expectType<RequestHeadersDefault & RawRequestDefaultExpression['headers']>(request.headers)
|
|
88
88
|
request.headers = {}
|
package/types/request.d.ts
CHANGED
|
@@ -22,10 +22,11 @@ export interface ValidationFunction {
|
|
|
22
22
|
|
|
23
23
|
export interface RequestRouteOptions<ContextConfig = ContextConfigDefault, SchemaCompiler = FastifySchema> {
|
|
24
24
|
method: string;
|
|
25
|
-
url
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
// `url` can be `undefined` for instance when `request.is404` is true
|
|
26
|
+
url: string | undefined;
|
|
27
|
+
bodyLimit: number;
|
|
28
|
+
attachValidation: boolean;
|
|
29
|
+
logLevel: string;
|
|
29
30
|
version: string | undefined;
|
|
30
31
|
exposeHeadRoute: boolean;
|
|
31
32
|
prefixTrailingSlash: string;
|
package/.vscode/settings.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"workbench.colorCustomizations": {
|
|
3
|
-
"[GitHub Dark]": {
|
|
4
|
-
"tab.activeBackground": "#0d0d0d",
|
|
5
|
-
"tab.activeBorder": "#ffff00"
|
|
6
|
-
},
|
|
7
|
-
"activityBar.background": "#BEE077",
|
|
8
|
-
"activityBar.foreground": "#1C6B58",
|
|
9
|
-
"activityBar.inactiveForeground": "#444444",
|
|
10
|
-
"activityBar.activeBorder": "#411f88",
|
|
11
|
-
"activityBar.activeBackground": "#2F9980",
|
|
12
|
-
"activityBar.border": "#2F9980",
|
|
13
|
-
"titleBar.activeBackground": "#A6D83D",
|
|
14
|
-
"titleBar.activeForeground": "#1C6B58",
|
|
15
|
-
"titleBar.inactiveBackground": "#9cbb5a",
|
|
16
|
-
"titleBar.inactiveForeground": "#444444",
|
|
17
|
-
"titleBar.border": "#2F9980",
|
|
18
|
-
"statusBar.background": "#98C538",
|
|
19
|
-
"statusBar.foreground": "#1C6B58",
|
|
20
|
-
"statusBar.border": "#2F9980"
|
|
21
|
-
}
|
|
22
|
-
}
|