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). |