fastify
Version:
Fast and low overhead web framework, for Node.js
184 lines (142 loc) • 5.81 kB
Markdown
<h1 align="center">Fastify</h1>
## Decorators
If you need to add functionality to the Fastify instance, the `decorate` API is what you need.
The API allows you to add new properties to the Fastify instance. A value is not restricted to a function and could also be an object or a string, for example.
<a name="usage"></a>
### Usage
<a name="decorate"></a>
**decorate**
Just call the `decorate` API and pass the name of the new property and its value.
```js
fastify.decorate('utility', () => {
// something very useful
})
```
As said above, you can also decorate the instance with non-function values:
```js
fastify.decorate('conf', {
db: 'some.db',
port: 3000
})
```
Once you decorate the instance, you can access the value by using the name you passed as a parameter:
```js
fastify.utility()
console.log(fastify.conf.db)
```
<a name="decorate-reply"></a>
**decorateReply**
As the name suggests, this API is needed if you want to add new methods to the `Reply` core object. Just call the `decorateReply` API and pass the name of the new property and its value:
```js
fastify.decorateReply('utility', function () {
// something very useful
})
```
Note: using an arrow function will break the binding of `this` to the Fastify `reply` instance.
<a name="decorate-request"></a>
**decorateRequest**
As above, this API is needed if you want to add new methods to the `Request` core object. Just call the `decorateRequest` API and pass the name of the new property and its value:
```js
fastify.decorateRequest('utility', function () {
// something very useful
})
```
Note: using an arrow function will break the binding of `this` to the Fastify `request` instance.
<a name="decorators-encapsulation"></a>
#### Decorators and encapsulation
If you define a decorator (using decorate, decorateRequest or decorateReply) with the same name more than once in the same **encapsulated** plugin, fastify will throw an exception.
As an example, the following will throw:
```js
const server = require('fastify')()
server.decorateReply('view', function (template, args) {
// Amazing vew rendering engine.
})
server.get('/', (req, reply) => {
reply.view('/index.html', { hello: 'world' })
})
// Somewhere else in our codebase, we define another
// view decorator. This throws.
server.decorateReply('view', function (template, args) {
// another rendering engine
})
server.listen(3000)
```
But this will not:
```js
const server = require('fastify')()
server.decorateReply('view', function (template, args) {
// Amazing vew rendering engine.
})
server.register(async function (server, opts) {
// We add a view decorator to the current encapsulated
// plugin. This will not throw as outside of this encapsulated
// plugin view is the old one, while inside it is the new one.
server.decorateReply('view', function (template, args) {
// another rendering engine
})
server.get('/', (req, reply) => {
reply.view('/index.page', { hello: 'world' })
})
}, { prefix: '/bar' })
server.listen(3000)
```
<a name="getters-setters"></a>
#### Getters and Setters
Decorators accept special "getter/setter" objects. These objects have functions named `getter` and `setter` (though, the `setter` function is optional). This allows defining properties via decorators. For example:
```js
fastify.decorate('foo', {
getter () {
return 'a getter'
}
})
```
Will define the `foo` property on the *Fastify* instance:
```js
console.log(fastify.foo) // 'a getter'
```
<a name="usage_notes"></a>
#### Usage Notes
`decorateReply` and `decorateRequest` are used to modify the `Reply` and `Request` constructors respectively by adding methods or properties. To update these properties you should directly access the desired property of the `Reply` or `Request` object.
As an example let's add a user property to the `Request` object:
```js
// Decorate request with a 'user' property
fastify.decorateRequest('user', '')
// Update our property
fastify.addHook('preHandler', (req, reply, next) => {
req.user = 'Bob Dylan'
next()
})
// And finally access it
fastify.get('/', (req, reply) => {
reply.send(`Hello ${req.user}!`)
})
```
Note: The usage of `decorateReply` and `decorateRequest` is optional in this case but will allow Fastify to optimize for performance.
<a name="sync-async"></a>
#### Sync and Async
`decorate` is a *synchronous* API. If you need to add a decorator that has an *asynchronous* bootstrap, Fastify could boot up before your decorator is ready. To avoid this issue, you must use the `register` API in combination with `fastify-plugin`. To learn more, check out the [Plugins](https://github.com/fastify/fastify/blob/master/docs/Plugins.md) documentation as well.
<a name="dependencies"></a>
#### Dependencies
If your decorator depends on another decorator, you can easily declare the other decorator as a dependency. You just need to add an array of strings (representing the names of the decorators on which yours depends) as the third parameter:
```js
fastify.decorate('utility', fn, ['greet', 'log'])
```
If a dependency is not satisfied, `decorate` will throw an exception, but don't worry: the dependency check is executed before the server boots up, so it won't ever happen at runtime.
<a name="has-decorator"></a>
#### hasDecorator
You can check for the presence of a decorator with the `hasDecorator` API:
```js
fastify.hasDecorator('utility')
```
<a name="has-request-decorator"></a>
#### hasRequestDecorator
You can check for the presence of a Request decorator with the `hasRequestDecorator` API:
```js
fastify.hasRequestDecorator('utility')
```
<a name="has-reply-decorator"></a>
#### hasReplyDecorator
You can check for the presence of a Reply decorator with the `hasReplyDecorator` API:
```js
fastify.hasReplyDecorator('utility')
```