Skip to content

Commit

Permalink
[ci skip] bump docs
Browse files Browse the repository at this point in the history
  • Loading branch information
StarpTech committed Oct 6, 2018
1 parent 3f51de8 commit 8046131
Show file tree
Hide file tree
Showing 3 changed files with 285 additions and 0 deletions.
4 changes: 4 additions & 0 deletions website/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2420,6 +2420,10 @@
"version-6.0.1-reference": {
"title": "Reference",
"sidebar_label": "Reference"
},
"version-6.1.0-plugin": {
"title": "Plugin",
"sidebar_label": "Plugin"
}
},
"links": {
Expand Down
280 changes: 280 additions & 0 deletions website/versioned_docs/version-6.1.0/plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
---
id: version-6.1.0-plugin
title: Plugin
sidebar_label: Plugin
original_id: plugin
---

Hemera's plugin system based on the powerful [Avvio](https://github.com/mcollina/avvio) package. Avvio is fully reentrant and graph-based. You can load components/plugins within plugins, and be still sure that things will happen in the right order.

> Plugins should encourage you to encapsulate a domain specific context in a reusable piece of software. Great practice is to seperate plugins by a different topic name.
## Plugin helper library

Before we get into the plugin system of hemera you have to install a package called [`hemera-plugin`](https://github.com/hemerajs/hemera/tree/master/packages/hemera-plugin). This package can do some things for you:

- Check the bare-minimum version of Hemera
- Provide consistent interface to register plugins even when the api is changed
- Pass metadata to intialize your plugin with correct dependencies, default options and name
- Skip plugin encapsulation

## Create a plugin

```js
const hp = require('hemera-plugin')
const myPlugin = hp((hemera, opts, done) => {
const topic = 'math'

hemera.add(
{
topic,
cmd: 'add'
},
function(req, cb) {
cb(null, {
result: req.a + req.b
})
}
)

done()
}, '>=5.0.0')

module.exports = myPlugin
```

> Plugins are **encapsulated** "_scoped_" by default. If you define an extension inside it will only effects the actions in your plugin. You can disable it if you set the hemera plugin option `scoped:false`.
## Break encapsulation

Sometimes it is still useful to write a plugin which effects child as well as sibling scopes. You can archive this with plugin option `scoped: false` property. This approach is used in payload validators `hemera-joi` or authentication `hemera-jwt`.

```js
const hp = require('hemera-plugin')
const myPlugin = hp(
(hemera, opts, done) => {
const topic = 'math'

hemera.ext('onClientPostRequest', function(ctx, next) {
// some code
next()
})

done()
},
{ scoped: false }
)

hemera.use(myPlugin)
```

## Register child plugins

You can load plugins inside other plugins. Be ware that [**Scoped sensitive settings**](#scoped-sensitive-settings) are effected.

```js
const hp = require('hemera-plugin')
const myPlugin = hp((hemera, opts, done) => {
const topic = 'math'

hemera.ext('onClientPostRequest', function(ctx, next) {
// some code
next()
})

hemera.use(
hp((hemera, opts, done) => {
// some code
// this plugin will be effected by the 'onClientPostRequest' extension
done()
})
)

done()
})
```

### Decorators

Decorators are something special. Even if you create a plugin scope you can decorate the root hemera instance. Decorators are primarly used to expose data or functionality to other plugins.

```js
const hp = require('hemera-plugin')
const myPlugin = hp((hemera, opts, done) => {
const topic = 'math'

hemera.decorate('test', 1)

done()
})

hemera.use(myPlugin)
hemera.ready(() => console.log(hemera.test))
```

### Expose

If you want to share data inside a plugin you can use `expose()` it will effects all sibling and child scopes. Expose should be used to control the inner workings of the plugin.

```js
const hp = require('hemera-plugin')
const myPlugin = hp((hemera, opts, done) => {
const topic = 'math'

hemera.expose('cache', new Map())
hemera.cache.set('key', 'value')

hemera.use(myPlugin2) // cache is available in this plugin too

done()
})

hemera.use(myPlugin)
hemera.ready()
```

### Global registration

Sometimes it's still useful to write a plugin which effects sibling and child scopes. You can disable the creation of a plugin scope with the `scoped: false` property.
This approach is used in payload validators `hemera-joi` or authentication plugins like `hemera-jwt`.

```js
const hp = require('hemera-plugin')
const myPlugin = hp(
(hemera, opts, done) => {
const topic = 'math'

hemera.ext('onServerPreRequest', function(ctx, next) {
// some code
next()
})

done()
},
{
scoped: false
}
)

hemera.use(myPlugin)
```

### Scoped sensitive settings

- [Request/Response Extensions](extension.md#server-client-lifecycle)
- [Decorators](decorator.md)
- [Schema Compilers](payload-validation.md#use-your-custom-validator)
- [Codecs](codec.md)
- [Not found pattern](notfound-pattern.md)

## Add plugin metadata

```js
const hp = require('hemera-plugin')
const myPlugin = hp(
async (hemera, opts) => {
const topic = 'math'

hemera.add(
{
topic,
cmd: 'add'
},
function(req, cb) {
cb(null, {
result: req.a + req.b
})
}
)
},
{
hemera: '0.x', // bare-minimum version of Hemera
name: 'my-plugin', // name of your plugin, will be used e.g for logging purposes
options: { host: 'localhost', port: 8003 }, // default options for your plugin
dependencies: ['plugin2'],
decorators: ['joi']
}
)

hemera.use(myPlugin)
```

## Plugin depdendencies

You can declare plugins and decorators as dependencies. The constrains are checked when all plugins are registered.

```js
const hp = require('hemera-plugin')
const myPlugin = hp(
(hemera, opts, done) => {
const Joi = hemera.joi

done()
},
{
dependencies: ['plugin2'],
decorators: ['joi']
}
)

hemera.use(myPlugin)
hemera.ready(err => {
// The dependency 'hemera-joi' is not registered
})
```

## Async / Await

You can also pass an async function and omit the `done` callback.

```js
const hp = require('hemera-plugin')
const myPlugin = hp(async (hemera, opts) => {
const topic = 'math'

hemera.add(
{
topic,
cmd: 'add'
},
function(req, cb) {
cb(null, {
result: req.a + req.b
})
}
)
})
```

## Plugin registration

A plugin must be registered before the `ready` function is called. The ready function will initialize all plugins. Default plugin options are preserved if you don't overwrite them.

```js
hemera.use(plugin, { a: 1 })
```

## After

Calls a function after all previous registrations are loaded, including all their dependencies. This can be used to defer the registration of a plugin.

```js
hemera.use(plugin).after(cb)
// or
hemera.use(plugin)
hemera.after(cb)
```

## Plugin timeout

If you need to handle a lot of plugins you could run into timeout issues e.g if your forgot to call the callback or when no promise was resolved. These errors are hard to track. In order to find out which plugin caused it you can specify a `pluginTimeout`.
The error contains a property `fn` which contains your plugin functions all associated informations about your plugin.

```js
new Hemera(nats, { pluginTimeout: 100 })
hemera.use(plugin)
hemera.use(err => {
err.fn.name // the name of the plugin function
err.fn[Symbol.for('plugin-meta')] // all plugin informations like name or options
})
```
1 change: 1 addition & 0 deletions website/versions.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[
"6.1.0",
"6.0.1",
"6.0.0",
"5.8.6",
Expand Down

0 comments on commit 8046131

Please sign in to comment.