You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					490 lines
				
				15 KiB
			
		
		
			
		
	
	
					490 lines
				
				15 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								<h1 align="center">Fastify</h1>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# The hitchhiker's guide to plugins
							 | 
						||
| 
								 | 
							
								First of all, `DON'T PANIC`!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Fastify was built from the beginning to be an extremely modular system. We built
							 | 
						||
| 
								 | 
							
								a powerful API that allows you to add methods and utilities to Fastify by
							 | 
						||
| 
								 | 
							
								creating a namespace. We built a system that creates an encapsulation model,
							 | 
						||
| 
								 | 
							
								which allows you to split your application into multiple microservices at any
							 | 
						||
| 
								 | 
							
								moment, without the need to refactor the entire application.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								**Table of contents**
							 | 
						||
| 
								 | 
							
								- [The hitchhiker's guide to plugins](#the-hitchhikers-guide-to-plugins)
							 | 
						||
| 
								 | 
							
								  - [Register](#register)
							 | 
						||
| 
								 | 
							
								  - [Decorators](#decorators)
							 | 
						||
| 
								 | 
							
								  - [Hooks](#hooks)
							 | 
						||
| 
								 | 
							
								  - [How to handle encapsulation and
							 | 
						||
| 
								 | 
							
								    distribution](#how-to-handle-encapsulation-and-distribution)
							 | 
						||
| 
								 | 
							
								  - [ESM support](#esm-support)
							 | 
						||
| 
								 | 
							
								  - [Handle errors](#handle-errors)
							 | 
						||
| 
								 | 
							
								  - [Custom errors](#custom-errors)
							 | 
						||
| 
								 | 
							
								  - [Emit Warnings](#emit-warnings)
							 | 
						||
| 
								 | 
							
								  - [Let's start!](#lets-start)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Register
							 | 
						||
| 
								 | 
							
								<a id="register"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As with JavaScript, where everything is an object, in Fastify everything is a
							 | 
						||
| 
								 | 
							
								plugin.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Your routes, your utilities, and so on are all plugins. To add a new plugin,
							 | 
						||
| 
								 | 
							
								whatever its functionality may be, in Fastify you have a nice and unique API:
							 | 
						||
| 
								 | 
							
								[`register`](../Reference/Plugins.md).
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.register(
							 | 
						||
| 
								 | 
							
								  require('./my-plugin'),
							 | 
						||
| 
								 | 
							
								  { options }
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								`register` creates a new Fastify context, which means that if you perform any
							 | 
						||
| 
								 | 
							
								changes on the Fastify instance, those changes will not be reflected in the
							 | 
						||
| 
								 | 
							
								context's ancestors. In other words, encapsulation!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*Why is encapsulation important?*
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Well, let's say you are creating a new disruptive startup, what do you do? You
							 | 
						||
| 
								 | 
							
								create an API server with all your stuff, everything in the same place, a
							 | 
						||
| 
								 | 
							
								monolith!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Ok, you are growing very fast and you want to change your architecture and try
							 | 
						||
| 
								 | 
							
								microservices. Usually, this implies a huge amount of work, because of cross
							 | 
						||
| 
								 | 
							
								dependencies and a lack of separation of concerns in the codebase.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Fastify helps you in that regard. Thanks to the encapsulation model, it will
							 | 
						||
| 
								 | 
							
								completely avoid cross dependencies and will help you structure your code into
							 | 
						||
| 
								 | 
							
								cohesive blocks.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*Let's return to how to correctly use `register`.*
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As you probably know, the required plugins must expose a single function with
							 | 
						||
| 
								 | 
							
								the following signature
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								module.exports = function (fastify, options, done) {}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Where `fastify` is the encapsulated Fastify instance, `options` is the options
							 | 
						||
| 
								 | 
							
								object, and `done` is the function you **must** call when your plugin is ready.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Fastify's plugin model is fully reentrant and graph-based, it handles
							 | 
						||
| 
								 | 
							
								asynchronous code without any problems and it enforces both the load and close
							 | 
						||
| 
								 | 
							
								order of plugins. *How?* Glad you asked, check out
							 | 
						||
| 
								 | 
							
								[`avvio`](https://github.com/mcollina/avvio)! Fastify starts loading the plugin
							 | 
						||
| 
								 | 
							
								__after__ `.listen()`, `.inject()` or `.ready()` are called.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Inside a plugin you can do whatever you want, register routes, utilities (we
							 | 
						||
| 
								 | 
							
								will see this in a moment) and do nested registers, just remember to call `done`
							 | 
						||
| 
								 | 
							
								when everything is set up!
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								module.exports = function (fastify, options, done) {
							 | 
						||
| 
								 | 
							
								  fastify.get('/plugin', (request, reply) => {
							 | 
						||
| 
								 | 
							
								    reply.send({ hello: 'world' })
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Well, now you know how to use the `register` API and how it works, but how do we
							 | 
						||
| 
								 | 
							
								add new functionality to Fastify and even better, share them with other
							 | 
						||
| 
								 | 
							
								developers?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Decorators
							 | 
						||
| 
								 | 
							
								<a id="decorators"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Okay, let's say that you wrote a utility that is so good that you decided to
							 | 
						||
| 
								 | 
							
								make it available along with all your code. How would you do it? Probably
							 | 
						||
| 
								 | 
							
								something like the following:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								// your-awesome-utility.js
							 | 
						||
| 
								 | 
							
								module.exports = function (a, b) {
							 | 
						||
| 
								 | 
							
								  return a + b
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const util = require('./your-awesome-utility')
							 | 
						||
| 
								 | 
							
								console.log(util('that is ', 'awesome'))
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Now you will import your utility in every file you need it in. (And do not
							 | 
						||
| 
								 | 
							
								forget that you will probably also need it in your tests).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Fastify offers you a more elegant and comfortable way to do this, *decorators*.
							 | 
						||
| 
								 | 
							
								Creating a decorator is extremely easy, just use the
							 | 
						||
| 
								 | 
							
								[`decorate`](../Reference/Decorators.md) API:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorate('util', (a, b) => a + b)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Now you can access your utility just by calling `fastify.util` whenever you need
							 | 
						||
| 
								 | 
							
								it - even inside your test.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And here starts the magic; do you remember how just now we were talking about
							 | 
						||
| 
								 | 
							
								encapsulation? Well, using `register` and `decorate` in conjunction enable
							 | 
						||
| 
								 | 
							
								exactly that, let me show you an example to clarify this:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								  instance.decorate('util', (a, b) => a + b)
							 | 
						||
| 
								 | 
							
								  console.log(instance.util('that is ', 'awesome'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								  console.log(instance.util('that is ', 'awesome')) // This will throw an error
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Inside the second register call `instance.util` will throw an error because
							 | 
						||
| 
								 | 
							
								`util` exists only inside the first register context.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let's step back for a moment and dig deeper into this: every time you use the
							 | 
						||
| 
								 | 
							
								`register` API, a new context is created which avoids the negative situations
							 | 
						||
| 
								 | 
							
								mentioned above.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Do note that encapsulation applies to the ancestors and siblings, but not the
							 | 
						||
| 
								 | 
							
								children.
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								  instance.decorate('util', (a, b) => a + b)
							 | 
						||
| 
								 | 
							
								  console.log(instance.util('that is ', 'awesome'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								    console.log(instance.util('that is ', 'awesome')) // This will not throw an error
							 | 
						||
| 
								 | 
							
								    done()
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								  console.log(instance.util('that is ', 'awesome')) // This will throw an error
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								*Take home message: if you need a utility that is available in every part of
							 | 
						||
| 
								 | 
							
								your application, take care that it is declared in the root scope of your
							 | 
						||
| 
								 | 
							
								application. If that is not an option,  you can use the `fastify-plugin` utility
							 | 
						||
| 
								 | 
							
								as described [here](#distribution).*
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`decorate` is not the only API that you can use to extend the server
							 | 
						||
| 
								 | 
							
								functionality, you can also use `decorateRequest` and `decorateReply`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*`decorateRequest` and `decorateReply`? Why do we need them if we already have
							 | 
						||
| 
								 | 
							
								`decorate`?*
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Good question, we added them to make Fastify more developer-friendly. Let's see
							 | 
						||
| 
								 | 
							
								an example:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorate('html', payload => {
							 | 
						||
| 
								 | 
							
								  return generateHtml(payload)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/html', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply
							 | 
						||
| 
								 | 
							
								    .type('text/html')
							 | 
						||
| 
								 | 
							
								    .send(fastify.html({ hello: 'world' }))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								It works, but it could be much better!
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorateReply('html', function (payload) {
							 | 
						||
| 
								 | 
							
								  this.type('text/html') // This is the 'Reply' object
							 | 
						||
| 
								 | 
							
								  this.send(generateHtml(payload))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/html', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply.html({ hello: 'world' })
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In the same way you can do this for the `request` object:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorate('getHeader', (req, header) => {
							 | 
						||
| 
								 | 
							
								  return req.headers[header]
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.addHook('preHandler', (request, reply, done) => {
							 | 
						||
| 
								 | 
							
								  request.isHappy = fastify.getHeader(request.raw, 'happy')
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/happiness', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply.send({ happy: request.isHappy })
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Again, it works, but it can be much better!
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorateRequest('setHeader', function (header) {
							 | 
						||
| 
								 | 
							
								  this.isHappy = this.headers[header]
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.decorateRequest('isHappy', false) // This will be added to the Request object prototype, yay speed!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.addHook('preHandler', (request, reply, done) => {
							 | 
						||
| 
								 | 
							
								  request.setHeader('happy')
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/happiness', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply.send({ happy: request.isHappy })
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We have seen how to extend server functionality and how to handle the
							 | 
						||
| 
								 | 
							
								encapsulation system, but what if you need to add a function that must be
							 | 
						||
| 
								 | 
							
								executed every time when the server "[emits](../Reference/Lifecycle.md)" an
							 | 
						||
| 
								 | 
							
								event?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Hooks
							 | 
						||
| 
								 | 
							
								<a id="hooks"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You just built an amazing utility, but now you need to execute that for every
							 | 
						||
| 
								 | 
							
								request, this is what you will likely do:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorate('util', (request, key, value) => { request[key] = value })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/plugin1', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  fastify.util(request, 'timestamp', new Date())
							 | 
						||
| 
								 | 
							
								  reply.send(request)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/plugin2', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  fastify.util(request, 'timestamp', new Date())
							 | 
						||
| 
								 | 
							
								  reply.send(request)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								I think we all agree that this is terrible. Repeated code, awful readability and
							 | 
						||
| 
								 | 
							
								it cannot scale.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								So what can you do to avoid this annoying issue? Yes, you are right, use a
							 | 
						||
| 
								 | 
							
								[hook](../Reference/Hooks.md)!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.decorate('util', (request, key, value) => { request[key] = value })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.addHook('preHandler', (request, reply, done) => {
							 | 
						||
| 
								 | 
							
								  fastify.util(request, 'timestamp', new Date())
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/plugin1', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply.send(request)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/plugin2', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply.send(request)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Now for every request, you will run your utility. You can register as many hooks
							 | 
						||
| 
								 | 
							
								as you need.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Sometimes you want a hook that should be executed for just a subset of routes,
							 | 
						||
| 
								 | 
							
								how can you do that? Yep, encapsulation!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								  instance.decorate('util', (request, key, value) => { request[key] = value })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  instance.addHook('preHandler', (request, reply, done) => {
							 | 
						||
| 
								 | 
							
								    instance.util(request, 'timestamp', new Date())
							 | 
						||
| 
								 | 
							
								    done()
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  instance.get('/plugin1', (request, reply) => {
							 | 
						||
| 
								 | 
							
								    reply.send(request)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  done()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.get('/plugin2', (request, reply) => {
							 | 
						||
| 
								 | 
							
								  reply.send(request)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Now your hook will run just for the first route!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As you probably noticed by now, `request` and `reply` are not the standard
							 | 
						||
| 
								 | 
							
								Nodejs *request* and *response* objects, but Fastify's objects.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## How to handle encapsulation and distribution
							 | 
						||
| 
								 | 
							
								<a id="distribution"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Perfect, now you know (almost) all of the tools that you can use to extend
							 | 
						||
| 
								 | 
							
								Fastify. Nevertheless, chances are that you came across one big issue: how is
							 | 
						||
| 
								 | 
							
								distribution handled?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The preferred way to distribute a utility is to wrap all your code inside a
							 | 
						||
| 
								 | 
							
								`register`. Using this, your plugin can support asynchronous bootstrapping
							 | 
						||
| 
								 | 
							
								*(since `decorate` is a synchronous API)*, in the case of a database connection
							 | 
						||
| 
								 | 
							
								for example.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*Wait, what? Didn't you tell me that `register` creates an encapsulation and
							 | 
						||
| 
								 | 
							
								that the stuff I create inside will not be available outside?*
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Yes, I said that. However, what I didn't tell you is that you can tell Fastify
							 | 
						||
| 
								 | 
							
								to avoid this behavior with the
							 | 
						||
| 
								 | 
							
								[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module.
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								const dbClient = require('db-client')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function dbPlugin (fastify, opts, done) {
							 | 
						||
| 
								 | 
							
								  dbClient.connect(opts.url, (err, conn) => {
							 | 
						||
| 
								 | 
							
								    fastify.decorate('db', conn)
							 | 
						||
| 
								 | 
							
								    done()
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = fp(dbPlugin)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								You can also tell `fastify-plugin` to check the installed version of Fastify, in
							 | 
						||
| 
								 | 
							
								case you need a specific API.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As we mentioned earlier, Fastify starts loading its plugins __after__
							 | 
						||
| 
								 | 
							
								`.listen()`, `.inject()` or `.ready()` are called and as such, __after__ they
							 | 
						||
| 
								 | 
							
								have been declared. This means that, even though the plugin may inject variables
							 | 
						||
| 
								 | 
							
								to the external Fastify instance via [`decorate`](../Reference/Decorators.md),
							 | 
						||
| 
								 | 
							
								the decorated variables will not be accessible before calling `.listen()`,
							 | 
						||
| 
								 | 
							
								`.inject()` or `.ready()`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In case you rely on a variable injected by a preceding plugin and want to pass
							 | 
						||
| 
								 | 
							
								that in the `options` argument of `register`, you can do so by using a function
							 | 
						||
| 
								 | 
							
								instead of an object:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fastify = require('fastify')()
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								const dbClient = require('db-client')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function dbPlugin (fastify, opts, done) {
							 | 
						||
| 
								 | 
							
								  dbClient.connect(opts.url, (err, conn) => {
							 | 
						||
| 
								 | 
							
								    fastify.decorate('db', conn)
							 | 
						||
| 
								 | 
							
								    done()
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.register(fp(dbPlugin), { url: 'https://example.com' })
							 | 
						||
| 
								 | 
							
								fastify.register(require('your-plugin'), parent => {
							 | 
						||
| 
								 | 
							
								  return { connection: parent.db, otherOption: 'foo-bar' }
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								In the above example, the `parent` variable of the function passed in as the
							 | 
						||
| 
								 | 
							
								second argument of `register` is a copy of the **external Fastify instance**
							 | 
						||
| 
								 | 
							
								that the plugin was registered at. This means that we are able to access any
							 | 
						||
| 
								 | 
							
								variables that were injected by preceding plugins in the order of declaration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## ESM support
							 | 
						||
| 
								 | 
							
								<a id="esm-support"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ESM is supported as well from [Node.js
							 | 
						||
| 
								 | 
							
								`v13.3.0`](https://nodejs.org/api/esm.html) and above! Just export your plugin
							 | 
						||
| 
								 | 
							
								as ESM module and you are good to go!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								// plugin.mjs
							 | 
						||
| 
								 | 
							
								async function plugin (fastify, opts) {
							 | 
						||
| 
								 | 
							
								  fastify.get('/', async (req, reply) => {
							 | 
						||
| 
								 | 
							
								    return { hello: 'world' }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export default plugin
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								__Note__: Fastify does not support named imports within an ESM context. Instead,
							 | 
						||
| 
								 | 
							
								the `default` export is available.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								// server.mjs
							 | 
						||
| 
								 | 
							
								import Fastify from 'fastify'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								///...
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastify.listen(3000, (err, address) => {
							 | 
						||
| 
								 | 
							
								  if (err) {
							 | 
						||
| 
								 | 
							
								    fastify.log.error(err)
							 | 
						||
| 
								 | 
							
								    process.exit(1)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Handle errors
							 | 
						||
| 
								 | 
							
								<a id="handle-errors"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								It can happen that one of your plugins fails during startup. Maybe you expect it
							 | 
						||
| 
								 | 
							
								and you have a custom logic that will be triggered in that case. How can you
							 | 
						||
| 
								 | 
							
								implement this? The `after` API is what you need. `after` simply registers a
							 | 
						||
| 
								 | 
							
								callback that will be executed just after a register, and it can take up to
							 | 
						||
| 
								 | 
							
								three parameters.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The callback changes based on the parameters you are giving:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1. If no parameter is given to the callback and there is an error, that error
							 | 
						||
| 
								 | 
							
								   will be passed to the next error handler.
							 | 
						||
| 
								 | 
							
								1. If one parameter is given to the callback, that parameter will be the error
							 | 
						||
| 
								 | 
							
								   object.
							 | 
						||
| 
								 | 
							
								1. If two parameters are given to the callback, the first will be the error
							 | 
						||
| 
								 | 
							
								   object; the second will be the done callback.
							 | 
						||
| 
								 | 
							
								1. If three parameters are given to the callback, the first will be the error
							 | 
						||
| 
								 | 
							
								   object, the second will be the top-level context unless you have specified
							 | 
						||
| 
								 | 
							
								   both server and override, in that case, the context will be what the override
							 | 
						||
| 
								 | 
							
								   returns, and the third the done callback.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let's see how to use it:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fastify
							 | 
						||
| 
								 | 
							
								  .register(require('./database-connector'))
							 | 
						||
| 
								 | 
							
								  .after(err => {
							 | 
						||
| 
								 | 
							
								    if (err) throw err
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Custom errors
							 | 
						||
| 
								 | 
							
								<a id="custom-errors"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If your plugin needs to expose custom errors, you can easily generate consistent
							 | 
						||
| 
								 | 
							
								error objects across your codebase and plugins with the
							 | 
						||
| 
								 | 
							
								[`@fastify/error`](https://github.com/fastify/fastify-error) module.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const createError = require('@fastify/error')
							 | 
						||
| 
								 | 
							
								const CustomError = createError('ERROR_CODE', 'message')
							 | 
						||
| 
								 | 
							
								console.log(new CustomError())
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Emit Warnings
							 | 
						||
| 
								 | 
							
								<a id="emit-warnings"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you want to deprecate an API, or you want to warn the user about a specific
							 | 
						||
| 
								 | 
							
								use case, you can use the
							 | 
						||
| 
								 | 
							
								[`fastify-warning`](https://github.com/fastify/fastify-warning) module.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const warning = require('fastify-warning')()
							 | 
						||
| 
								 | 
							
								warning.create('FastifyDeprecation', 'FST_ERROR_CODE', 'message')
							 | 
						||
| 
								 | 
							
								warning.emit('FST_ERROR_CODE')
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Let's start!
							 | 
						||
| 
								 | 
							
								<a id="start"></a>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Awesome, now you know everything you need to know about Fastify and its plugin
							 | 
						||
| 
								 | 
							
								system to start building your first plugin, and please if you do, tell us! We
							 | 
						||
| 
								 | 
							
								will add it to the [*ecosystem*](https://github.com/fastify/fastify#ecosystem)
							 | 
						||
| 
								 | 
							
								section of our documentation!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you want to see some real-world examples, check out:
							 | 
						||
| 
								 | 
							
								- [`point-of-view`](https://github.com/fastify/point-of-view) Templates
							 | 
						||
| 
								 | 
							
								  rendering (*ejs, pug, handlebars, marko*) plugin support for Fastify.
							 | 
						||
| 
								 | 
							
								- [`@fastify/mongodb`](https://github.com/fastify/fastify-mongodb) Fastify
							 | 
						||
| 
								 | 
							
								  MongoDB connection plugin, with this you can share the same MongoDB connection
							 | 
						||
| 
								 | 
							
								  pool in every part of your server.
							 | 
						||
| 
								 | 
							
								- [`@fastify/multipart`](https://github.com/fastify/fastify-multipart) Multipart
							 | 
						||
| 
								 | 
							
								  support for Fastify
							 | 
						||
| 
								 | 
							
								- [`@fastify/helmet`](https://github.com/fastify/fastify-helmet) Important
							 | 
						||
| 
								 | 
							
								  security headers for Fastify
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*Do you feel like something is missing here? Let us know! :)*
							 |