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.
		
		
		
		
		
			
		
			
				
					183 lines
				
				6.1 KiB
			
		
		
			
		
	
	
					183 lines
				
				6.1 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# fastify-plugin
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[](https://www.npmjs.com/package/fastify-plugin)
							 | 
						||
| 
								 | 
							
								[](https://standardjs.com/)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`fastify-plugin` is a plugin helper for [Fastify](https://github.com/fastify/fastify).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When you build plugins for Fastify and you want that them to be accessible in the same context where you require them, you have two ways:
							 | 
						||
| 
								 | 
							
								1. Use the `skip-override` hidden property
							 | 
						||
| 
								 | 
							
								2. Use this module
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								__Note: the v4.x series of this module covers Fastify v4__
							 | 
						||
| 
								 | 
							
								__Note: the v2.x & v3.x series of this module covers Fastify v3. For Fastify v2 support, refer to the v1.x series.__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Usage
							 | 
						||
| 
								 | 
							
								`fastify-plugin` can do three things for you:
							 | 
						||
| 
								 | 
							
								- Add the `skip-override` hidden property
							 | 
						||
| 
								 | 
							
								- Check the bare-minimum version of Fastify
							 | 
						||
| 
								 | 
							
								- Pass some custom metadata of the plugin to Fastify
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Example using a callback:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = fp(function (fastify, opts, next) {
							 | 
						||
| 
								 | 
							
								  // your plugin code
							 | 
						||
| 
								 | 
							
								  next()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Example using an [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// A callback function param is not required for async functions
							 | 
						||
| 
								 | 
							
								module.exports = fp(async function (fastify, opts) {
							 | 
						||
| 
								 | 
							
								  // Wait for an async function to fulfill promise before proceeding
							 | 
						||
| 
								 | 
							
								  await exampleAsyncFunction()
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Metadata
							 | 
						||
| 
								 | 
							
								In addition, if you use this module when creating new plugins, you can declare the dependencies, the name, and the expected Fastify version that your plugin needs.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Fastify version
							 | 
						||
| 
								 | 
							
								If you need to set a bare-minimum version of Fastify for your plugin, just add the [semver](https://semver.org/) range that you need:
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = fp(function (fastify, opts, next) {
							 | 
						||
| 
								 | 
							
								  // your plugin code
							 | 
						||
| 
								 | 
							
								  next()
							 | 
						||
| 
								 | 
							
								}, { fastify: '4.x' })
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you need to check the Fastify version only, you can pass just the version string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You can check [here](https://github.com/npm/node-semver#ranges) how to define a `semver` range.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Name
							 | 
						||
| 
								 | 
							
								Fastify uses this option to validate the dependency graph, allowing it to ensure that no name collisions occur and making it possible to perform [dependency checks](https://github.com/fastify/fastify-plugin#dependencies).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function plugin (fastify, opts, next) {
							 | 
						||
| 
								 | 
							
								  // your plugin code
							 | 
						||
| 
								 | 
							
								  next()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = fp(plugin, {
							 | 
						||
| 
								 | 
							
								  fastify: '4.x',
							 | 
						||
| 
								 | 
							
								  name: 'your-plugin-name'
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Dependencies
							 | 
						||
| 
								 | 
							
								You can also check if the `plugins` and `decorators` that your plugin intend to use are present in the dependency graph.
							 | 
						||
| 
								 | 
							
								> *Note:* This is the point where registering `name` of the plugins become important, because you can reference `plugin` dependencies by their [name](https://github.com/fastify/fastify-plugin#name).
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function plugin (fastify, opts, next) {
							 | 
						||
| 
								 | 
							
								  // your plugin code
							 | 
						||
| 
								 | 
							
								  next()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = fp(plugin, {
							 | 
						||
| 
								 | 
							
								  fastify: '4.x',
							 | 
						||
| 
								 | 
							
								  decorators: {
							 | 
						||
| 
								 | 
							
								    fastify: ['plugin1', 'plugin2'],
							 | 
						||
| 
								 | 
							
								    reply: ['compress']
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  dependencies: ['plugin1-name', 'plugin2-name']
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Encapsulate
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								By default, `fastify-plugin` breaks the [encapsulation](https://github.com/fastify/fastify/blob/HEAD/docs/Reference/Encapsulation.md) but you can optionally keep the plugin encapsulated.
							 | 
						||
| 
								 | 
							
								This allows you to set the plugin's name and validate its dependencies without making the plugin accessible.
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function plugin (fastify, opts, next) {
							 | 
						||
| 
								 | 
							
								  // the decorator is not accessible outside this plugin
							 | 
						||
| 
								 | 
							
								  fastify.decorate('util', function() {})
							 | 
						||
| 
								 | 
							
								  next()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = fp(plugin, {
							 | 
						||
| 
								 | 
							
								  name: 'my-encapsulated-plugin',
							 | 
						||
| 
								 | 
							
								  fastify: '4.x',
							 | 
						||
| 
								 | 
							
								  decorators: {
							 | 
						||
| 
								 | 
							
								    fastify: ['plugin1', 'plugin2'],
							 | 
						||
| 
								 | 
							
								    reply: ['compress']
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  dependencies: ['plugin1-name', 'plugin2-name'],
							 | 
						||
| 
								 | 
							
								  encapsulate: true
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Bundlers and Typescript
							 | 
						||
| 
								 | 
							
								`fastify-plugin` adds a `.default` and `[name]` property to the passed in function.
							 | 
						||
| 
								 | 
							
								The type definition would have to be updated to leverage this.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Known Issue: TypeScript Contextual Inference
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[Documentation Reference](https://www.typescriptlang.org/docs/handbook/functions.html#inferring-the-types)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								It is common for developers to inline their plugin with fastify-plugin such as:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								fp((fastify, opts, next) => { next() })
							 | 
						||
| 
								 | 
							
								fp(async (fastify, opts) => { return })
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TypeScript can sometimes infer the types of the arguments for these functions. Plugins in fastify are recommended to be typed using either `FastifyPluginCallback` or `FastifyPluginAsync`. These two definitions only differ in two ways:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1. The third argument `next` (the callback part)
							 | 
						||
| 
								 | 
							
								2. The return type `FastifyPluginCallback` or `FastifyPluginAsync`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								At this time, TypeScript inference is not smart enough to differentiate by definition argument length alone.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Thus, if you are a TypeScript developer please use on the following patterns instead:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```ts
							 | 
						||
| 
								 | 
							
								// Callback
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Assign type directly
							 | 
						||
| 
								 | 
							
								const pluginCallback: FastifyPluginCallback = (fastify, options, next) => { }
							 | 
						||
| 
								 | 
							
								fp(pluginCallback)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// or define your own function declaration that satisfies the existing definitions
							 | 
						||
| 
								 | 
							
								const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { }
							 | 
						||
| 
								 | 
							
								fp(pluginCallbackWithTypes)
							 | 
						||
| 
								 | 
							
								// or inline
							 | 
						||
| 
								 | 
							
								fp((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Async
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Assign type directly
							 | 
						||
| 
								 | 
							
								const pluginAsync: FastifyPluginAsync = async (fastify, options) => { }
							 | 
						||
| 
								 | 
							
								fp(pluginAsync)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// or define your own function declaration that satisfies the existing definitions
							 | 
						||
| 
								 | 
							
								const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { }
							 | 
						||
| 
								 | 
							
								fp(pluginAsyncWithTypes)
							 | 
						||
| 
								 | 
							
								// or inline
							 | 
						||
| 
								 | 
							
								fp(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { })
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Acknowledgements
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This project is kindly sponsored by:
							 | 
						||
| 
								 | 
							
								- [nearForm](https://nearform.com)
							 | 
						||
| 
								 | 
							
								- [LetzDoIt](https://www.letzdoitapp.com/)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## License
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Licensed under [MIT](./LICENSE).
							 |