fastify 4.26.1 → 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.
@@ -287,6 +287,8 @@ async function migrate() {
287
287
  });
288
288
 
289
289
  try {
290
+ await client.connect();
291
+
290
292
  const postgrator = new Postgrator({
291
293
  migrationPattern: path.join(__dirname, '/migrations/*'),
292
294
  driver: 'pg',
@@ -529,6 +529,8 @@ middlewares into Fastify plugins
529
529
  across every part of your server.
530
530
  - [`fastify-osm`](https://github.com/gzileni/fastify-osm) Fastify
531
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
532
534
  - [`fastify-peekaboo`](https://github.com/simone-sanfratello/fastify-peekaboo)
533
535
  Fastify plugin for memoize responses by expressive settings.
534
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
- export.fastifyFunction = fastifyFunction;
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
@@ -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](#jsonschema).
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)
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.1'
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
  }
@@ -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/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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "4.26.1",
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",
@@ -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 79 errors', t => {
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, 79)
17
+ t.equal(counter, 80)
18
18
  })
19
19
 
20
20
  test('ensure name and codes of Errors are identical', t => {
21
- t.plan(79)
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(79)
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(79)
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(79)
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(79)
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
@@ -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'