strong-tie/inbound-calls
0
1<h1 align="center">Fastify</h1>2 3## Plugins4Fastify allows the user to extend its functionalities with plugins. A plugin can5be a set of routes, a server [decorator](./Decorators.md), or whatever. The API6that you will need to use one or more plugins, is `register`.7 8By default, `register` creates a *new scope*, this means that if you make some9changes to the Fastify instance (via `decorate`), this change will not be10reflected by the current context ancestors, but only by its descendants. This11feature allows us to achieve plugin *encapsulation* and *inheritance*, in this12way we create a *directed acyclic graph* (DAG) and we will not have issues13caused by cross dependencies.14 15You may have already seen in the [Getting16Started](../Guides/Getting-Started.md#your-first-plugin) guide how easy it is17to use this API:18```19fastify.register(plugin, [options])20```21 22### Plugin Options23<a id="plugin-options"></a>24 25The optional `options` parameter for `fastify.register` supports a predefined26set of options that Fastify itself will use, except when the plugin has been27wrapped with [fastify-plugin](https://github.com/fastify/fastify-plugin). This28options object will also be passed to the plugin upon invocation, regardless of29whether or not the plugin has been wrapped. The currently supported list of30Fastify specific options is:31 32+ [`logLevel`](./Routes.md#custom-log-level)33+ [`logSerializers`](./Routes.md#custom-log-serializer)34+ [`prefix`](#route-prefixing-option)35 36**Note: Those options will be ignored when used with fastify-plugin**37 38It is possible that Fastify will directly support other options in the future.39Thus, to avoid collisions, a plugin should consider namespacing its options. For40example, a plugin `foo` might be registered like so:41 42```js43fastify.register(require('fastify-foo'), {44 prefix: '/foo',45 foo: {46 fooOption1: 'value',47 fooOption2: 'value'48 }49})50```51 52If collisions are not a concern, the plugin may simply accept the options object53as-is:54 55```js56fastify.register(require('fastify-foo'), {57 prefix: '/foo',58 fooOption1: 'value',59 fooOption2: 'value'60})61```62 63The `options` parameter can also be a `Function` that will be evaluated at the64time the plugin is registered while giving access to the Fastify instance via65the first positional argument:66 67```js68const fp = require('fastify-plugin')69 70fastify.register(fp((fastify, opts, done) => {71 fastify.decorate('foo_bar', { hello: 'world' })72 73 done()74}))75 76// The opts argument of fastify-foo will be { hello: 'world' }77fastify.register(require('fastify-foo'), parent => parent.foo_bar)78```79 80The Fastify instance passed on to the function is the latest state of the81**external Fastify instance** the plugin was declared on, allowing access to82variables injected via [`decorate`](./Decorators.md) by preceding plugins83according to the **order of registration**. This is useful in case a plugin84depends on changes made to the Fastify instance by a preceding plugin i.e.85utilizing an existing database connection to wrap around it.86 87Keep in mind that the Fastify instance passed on to the function is the same as88the one that will be passed into the plugin, a copy of the external Fastify89instance rather than a reference. Any usage of the instance will behave the same90as it would if called within the plugins function i.e. if `decorate` is called,91the decorated variables will be available within the plugins function unless it92was wrapped with [`fastify-plugin`](https://github.com/fastify/fastify-plugin).93 94#### Route Prefixing option95<a id="route-prefixing-option"></a>96 97If you pass an option with the key `prefix` with a `string` value, Fastify will98use it to prefix all the routes inside the register, for more info check99[here](./Routes.md#route-prefixing).100 101Be aware that if you wrap your routes with102[`fastify-plugin`](https://github.com/fastify/fastify-plugin), this option will103not work (there is a [workaround](./Routes.md#fastify-plugin) available).104 105#### Error handling106<a id="error-handling"></a>107 108The error handling is done by109[avvio](https://github.com/mcollina/avvio#error-handling).110 111As a general rule, it is highly recommended that you handle your errors in the112next `after` or `ready` block, otherwise you will get them inside the `listen`113callback.114 115```js116fastify.register(require('my-plugin'))117 118// `after` will be executed once119// the previous declared `register` has finished120fastify.after(err => console.log(err))121 122// `ready` will be executed once all the registers declared123// have finished their execution124fastify.ready(err => console.log(err))125 126// `listen` is a special ready,127// so it behaves in the same way128fastify.listen({ port: 3000 }, (err, address) => {129 if (err) console.log(err)130})131```132 133### async/await134<a id="async-await"></a>135 136*async/await* is supported by `after`, `ready`, and `listen`, as well as137`fastify` being a Thenable.138 139```js140await fastify.register(require('my-plugin'))141 142await fastify.after()143 144await fastify.ready()145 146await fastify.listen({ port: 3000 })147```148*Note: Using `await` when registering a plugin loads the plugin149and the underlying dependency tree, "finalizing" the encapsulation process.150Any mutations to the plugin after it and its dependencies have been151loaded will not be reflected in the parent instance.*152 153#### ESM support154<a id="esm-support"></a>155 156ESM is supported as well from [Node.js157`v13.3.0`](https://nodejs.org/api/esm.html) and above!158 159```js160// main.mjs161import Fastify from 'fastify'162const fastify = Fastify()163 164fastify.register(import('./plugin.mjs'))165 166fastify.listen({ port: 3000 }, console.log)167 168 169// plugin.mjs170async function plugin (fastify, opts) {171 fastify.get('/', async (req, reply) => {172 return { hello: 'world' }173 })174}175 176export default plugin177```178 179### Create a plugin180<a id="create-plugin"></a>181 182Creating a plugin is very easy, you just need to create a function that takes183three parameters, the `fastify` instance, an `options` object, and the `done`184callback.185 186Example:187```js188module.exports = function (fastify, opts, done) {189 fastify.decorate('utility', function () {})190 191 fastify.get('/', handler)192 193 done()194}195```196You can also use `register` inside another `register`:197```js198module.exports = function (fastify, opts, done) {199 fastify.decorate('utility', function () {})200 201 fastify.get('/', handler)202 203 fastify.register(require('./other-plugin'))204 205 done()206}207```208Sometimes, you will need to know when the server is about to close, for example,209because you must close a connection to a database. To know when this is going to210happen, you can use the [`'onClose'`](./Hooks.md#on-close) hook.211 212Do not forget that `register` will always create a new Fastify scope, if you do213not need that, read the following section.214 215### Handle the scope216<a id="handle-scope"></a>217 218If you are using `register` only for extending the functionality of the server219with [`decorate`](./Decorators.md), it is your responsibility to tell Fastify220not to create a new scope. Otherwise, your changes will not be accessible by the221user in the upper scope.222 223You have two ways to tell Fastify to avoid the creation of a new context:224- Use the [`fastify-plugin`](https://github.com/fastify/fastify-plugin) module225- Use the `'skip-override'` hidden property226 227We recommend using the `fastify-plugin` module, because it solves this problem228for you, and you can pass a version range of Fastify as a parameter that your229plugin will support.230```js231const fp = require('fastify-plugin')232 233module.exports = fp(function (fastify, opts, done) {234 fastify.decorate('utility', function () {})235 done()236}, '0.x')237```238Check the [`fastify-plugin`](https://github.com/fastify/fastify-plugin)239documentation to learn more about how to use this module.240 241If you do not use the `fastify-plugin` module, you can use the `'skip-override'`242hidden property, but we do not recommend it. If in the future the Fastify API243changes it will be your responsibility to update the module, while if you use244`fastify-plugin`, you can be sure about backward compatibility.245```js246function yourPlugin (fastify, opts, done) {247 fastify.decorate('utility', function () {})248 done()249}250yourPlugin[Symbol.for('skip-override')] = true251module.exports = yourPlugin252```253 