Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KZL-907] Getting started dev plugin #276

Merged
merged 23 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ee79d5b
archy plugin path
Yoann-Abbes Apr 10, 2019
b060caa
Merge branch '2-dev' into KZL-907-plugin-getting-started
Yoann-Abbes Apr 10, 2019
9787535
intro
Yoann-Abbes Apr 10, 2019
a58840a
archy plugin path
Yoann-Abbes Apr 10, 2019
320b5b1
boilerplate
Yoann-Abbes Apr 15, 2019
4214507
Merge branch '2-dev' into KZL-907-plugin-getting-started
Yoann-Abbes Apr 16, 2019
3de580d
request changes @benoitvidis
Yoann-Abbes Apr 16, 2019
e7b6ed2
markdown master
Yoann-Abbes Apr 16, 2019
2e4caca
Merge branch '2-dev' into KZL-907-plugin-getting-started
Yoann-Abbes Apr 17, 2019
eb0723c
requested changes @scottinet
Yoann-Abbes Apr 17, 2019
ab86825
Merge branch 'KZL-907-plugin-getting-started' of github.com:kuzzleio/…
Yoann-Abbes Apr 17, 2019
91cdbb4
requested changes @aschen
Yoann-Abbes Apr 17, 2019
4266a69
requested changes
Yoann-Abbes Apr 17, 2019
1ad5383
Update src/plugins/1/essentials/getting-started/index.md
Aschen Apr 23, 2019
6f551e3
Update src/plugins/1/essentials/getting-started/index.md
scottinet Apr 24, 2019
587052f
Update src/plugins/1/essentials/hooks/index.md
scottinet Apr 24, 2019
2959acb
getting started
Yoann-Abbes Apr 24, 2019
f911afb
requested changes @scottinet
Yoann-Abbes Apr 24, 2019
1870fbe
Update src/plugins/1/hooks/Documentation/index.md
scottinet Apr 25, 2019
3ea0ca8
Merge branch '2-dev' into KZL-907-plugin-getting-started
Yoann-Abbes Apr 25, 2019
289a7e2
Merge branch '2-dev' into KZL-907-plugin-getting-started
scottinet Apr 26, 2019
889d5e7
Merge branch '2-dev' into KZL-907-plugin-getting-started
scottinet Apr 26, 2019
64d002d
Merge branch '2-dev' into KZL-907-plugin-getting-started
Aschen Apr 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 15 additions & 23 deletions src/guide/1/essentials/plugins/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,31 @@ For example, imagine you are developing a mobile application that accesses a **t

Kuzzle's **[Plugin Engine]({{ site_base_path }}plugins/1)** is a powerful feature that ensures that Kuzzle meets any project requirement:

* select from a set of prebuilt plugins (such as the [OAuth2 Authentication Plugin](https://github.com/kuzzleio/kuzzle-plugin-auth-passport-oauth) or the [MQTT Protocol](https://github.com/kuzzleio/protocol-mqtt)).
* [create your own plugin]({{ site_base_path }}plugins/1/essentials) to meet your specific requirements.
- select from a set of prebuilt plugins (such as the [OAuth2 Authentication Plugin](https://github.com/kuzzleio/kuzzle-plugin-auth-passport-oauth) or the [MQTT Protocol](https://github.com/kuzzleio/protocol-mqtt)).
- [create your own plugin]({{ site_base_path }}plugins/1/essentials) to meet your specific requirements.

---

## Plugins

Plugins are used to extend Kuzzle's functionalities. They are loaded into Kuzzle during startup and share its execution thread. A plugin can implement one or multiple of the following interfaces:

[Hooks]({{ site_base_path }}plugins/1/essentials/hooks): adds asynchronous listeners that perform operations triggered by data events. When a listened event occurs, the data is sent to the listeners and Kuzzle continues its process without waiting for the listener to complete.
[Hooks]({{ site_base_path }}plugins/1/hooks): adds asynchronous listeners that perform operations triggered by data events. When a listened event occurs, the data is sent to the listeners and Kuzzle continues its process without waiting for the listener to complete.

_Example - "Write a log to a third-party logging service every time a document is deleted"_. The [Logger Plugin](https://github.com/kuzzleio/kuzzle-plugin-logger) (shipped with Kuzzle) uses this feature to log all the data-related events.
_Example - "Write a log to a third-party logging service every time a document is deleted"_. The [Logger Plugin](https://github.com/kuzzleio/kuzzle-plugin-logger) (shipped with Kuzzle) uses this feature to log all the data-related events.

[Pipes]({{ site_base_path }}plugins/1/essentials/pipes): adds synchronous listeners that perform operations triggered by data events. When a listened event occurs, the data is passed synchronously to listeners, each modifying the input data and returning the result to the next listener. Kuzzle waits until the last listener completes and returns its data. If any listener returns an error, it will interrupt the Kuzzle lifecycle, and the thrown error will be used as a response by Kuzzle.
[Pipes]({{ site_base_path }}plugins/1/pipes): adds synchronous listeners that perform operations triggered by data events. When a listened event occurs, the data is passed synchronously to listeners, each modifying the input data and returning the result to the next listener. Kuzzle waits until the last listener completes and returns its data. If any listener returns an error, it will interrupt the Kuzzle lifecycle, and the thrown error will be used as a response by Kuzzle.

_Example - "Compare the ordered quantity with the available stock and return an error if the amount of ordered items exceeds the amount in stock"_.
_Example - "Compare the ordered quantity with the available stock and return an error if the amount of ordered items exceeds the amount in stock"_.

[Controllers]({{ site_base_path }}plugins/1/essentials/controllers): extends Kuzzle API.
[Controllers]({{ site_base_path }}plugins/1/controllers): extends Kuzzle API.

_Example - "Expose a `checkout` API endpoint that handles a third-party payment process"_.
_Example - "Expose a `checkout` API endpoint that handles a third-party payment process"_.

[Strategies]({{ site_base_path }}plugins/1/essentials/strategies): add an authentication strategy to identify and authenticate users.

_Example - "Enable OAuth based authentication in Kuzzle"_
Kuzzle ships with the [Local Strategy Plugin](https://github.com/kuzzleio/kuzzle-plugin-auth-passport-local) and thanks to PassportJS, more than 300 authentication strategies are readily available.
_Example - "Enable OAuth based authentication in Kuzzle"_
Kuzzle ships with the [Local Strategy Plugin](https://github.com/kuzzleio/kuzzle-plugin-auth-passport-local) and thanks to PassportJS, more than 300 authentication strategies are readily available.

## Protocols

Expand All @@ -61,10 +61,8 @@ Prior to loading the plugin into Kuzzle, you will need to load all of the plugin

To demonstrate, we are going to install the [**Plugin Boilerplate**](https://github.com/kuzzleio/kuzzle-core-plugin-boilerplate), a plugin example that uses all features available to a plugin.


Go to the Kuzzle installation folder and type:


```bash
# Open plugins/available folder
cd plugins/available
Expand Down Expand Up @@ -105,13 +103,8 @@ Once Kuzzle has restarted, check the server information at `http://localhost:751
"document:beforeUpdate",
"core:overload"
],
"pipes": [
"document:beforeCreate",
"realtime:beforePublish"
],
"controllers": [
"kuzzle-core-plugin-boilerplate/myNewController"
],
"pipes": ["document:beforeCreate", "realtime:beforePublish"],
"controllers": ["kuzzle-core-plugin-boilerplate/myNewController"],
"routes": [
{
"verb": "get",
Expand All @@ -126,9 +119,7 @@ Once Kuzzle has restarted, check the server information at `http://localhost:751
"action": "myNewAction"
}
],
"strategies": [
"dummy"
]
"strategies": ["dummy"]
}
}
}
Expand All @@ -138,13 +129,13 @@ Once Kuzzle has restarted, check the server information at `http://localhost:751
```

Note that the plugin description above contains a property for each plugin component:

- `hooks` asynchronous operations that depend on data-related events
- `pipes` synchronous operations that depend on data-related events
- `controllers` list of exposed actions in the API
- `routes` list of exposed actions in the **REST** API
- `strategies` list of exposed authentication strategies


---

## Installing protocols
Expand Down Expand Up @@ -179,6 +170,7 @@ ln -s ../available/protocol-mqtt .
To get more insight into how plugins work, please refer to the [Plugin Reference]({{ site_base_path }}plugins/1).

Here is a list of official plugins:

- [**kuzzle-plugin-auth-passport-local**](https://github.com/kuzzleio/kuzzle-plugin-auth-passport-local): authentication Plugin shipped with Kuzzle
- [**kuzzle-plugin-logger**](https://github.com/kuzzleio/kuzzle-plugin-logger): plugin shipped with Kuzzle
- [**kuzzle-plugin-auth-passport-oauth**](https://github.com/kuzzleio/kuzzle-plugin-auth-passport-oauth): authentication plugin
Expand Down
19 changes: 9 additions & 10 deletions src/plugins/1/accessors/trigger/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ title: trigger

Triggers a custom event.

This allows interactions with other plugins using [hooks]({{ site_base_path }}plugins/1/essentials/hooks/) or [pipes]({{ site_base_path }}plugins/1/essentials/pipes/).
This allows interactions with other plugins using [hooks]({{ site_base_path }}plugins/1/hooks/) or [pipes]({{ site_base_path }}plugins/1/pipes/).

## Arguments

```js
trigger(event, [payload])
trigger(event, [payload]);
```

<br/>

| Arguments | Type | Description |
|-----------|------|-------------|
| `event` | <pre>string</pre> | Custom event name |
| `payload` | <pre>object</pre> | Event payload |
| Arguments | Type | Description |
| --------- | ----------------- | ----------------- |
| `event` | <pre>string</pre> | Custom event name |
| `payload` | <pre>object</pre> | Event payload |


**Note:** the triggered event is renamed using the following format:<br/>`plugin-<plugin name>:<event>`.
**Note:** the triggered event is renamed using the following format:<br/>`plugin-<plugin name>:<event>`.

## Example

Expand All @@ -37,13 +36,13 @@ context.accessors.trigger('someEvent', {

// Listening plugin
class ListeningPlugin {
constructor () {
constructor() {
this.hooks = {
'plugin-some-plugin:someEvent': 'someEventListener'
};
}

someEventListener (payload) {
someEventListener(payload) {
this.doSomething(payload);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
layout: full.html.hbs
title: Controllers
title: Documentation
order: 400
---

# Controllers

Kuzzle's API is divided into controllers, each exposing executable actions (see [API reference]({{ site_base_path }}api/1/essentials/query-syntax)).

Plugins can extend Kuzzle's API by adding new controllers to it.
Plugins can extend Kuzzle's API by adding new controllers to it.

[Security access]({{ site_base_path }}guide/1/essentials/security/) to plugin controllers must be given (or denied), using the exact same way as with native API controllers.

Expand All @@ -21,7 +21,7 @@ To avoid naming conflicts, Kuzzle prefixes plugin controllers names with the plu
### HTTP

```http
URL: http://<server>:<port>/_plugin/<plugin name>/<url defined by the plugin>/<resources>
URL: http://<server>:<port>/_plugin/<plugin name>/<url defined by the plugin>/<resources>
Method: <verb defined by the plugin>
```

Expand Down Expand Up @@ -53,16 +53,17 @@ Kuzzle normalizes [queries]({{ site_base_path }}api/1/essentials/query-syntax) i

Quick summary of how queries are normalized:

* HTTP:
* dynamic arguments provided in the URL, and query string arguments are stored in `request.input.args`
* the body content is made available in `request.input.body`
* if the URL contains an `index`, a `collection` or a `_id` argument, it will be stored in `request.input.resource`
* request headers can be found in `request.context.connection.misc.headers`
- HTTP:

* Other protocols:
* the `body` property is stored in `request.input.body`
* these root properties are available in `request.input.resource`: `index`, `collection`, `_id`
* any other properties at the root of the query object will be stored in `request.input.args`
- dynamic arguments provided in the URL, and query string arguments are stored in `request.input.args`
- the body content is made available in `request.input.body`
- if the URL contains an `index`, a `collection` or a `_id` argument, it will be stored in `request.input.resource`
- request headers can be found in `request.context.connection.misc.headers`

- Other protocols:
- the `body` property is stored in `request.input.body`
- these root properties are available in `request.input.resource`: `index`, `collection`, `_id`
- any other properties at the root of the query object will be stored in `request.input.args`

---

Expand All @@ -78,7 +79,7 @@ Read more about these automatic controller events [here]({{ site_base_path }}plu

```javascript
module.exports = class ControllerPlugin {
constructor () {
constructor() {
/*
Adds a new "newController" controller to Kuzzle's API.

Expand Down Expand Up @@ -128,16 +129,26 @@ module.exports = class ControllerPlugin {
property
*/
this.routes = [
{verb: 'get', url: '/foo/:name', controller: 'newController', action: 'myAction'},
{verb: 'post', url: '/bar', controller: 'newController', action: 'myOtherAction'}
{
verb: 'get',
url: '/foo/:name',
controller: 'newController',
action: 'myAction'
},
{
verb: 'post',
url: '/bar',
controller: 'newController',
action: 'myOtherAction'
}
];
}

/*
Required plugin initialization function
(see the "Plugin prerequisites" section)
*/
init (customConfig, context) {
init(customConfig, context) {
// plugin initialization
}

Expand All @@ -148,17 +159,20 @@ module.exports = class ControllerPlugin {
This result can be of any JS type (scalar, object, array), and
will be used to build a response to send to the requesting client
*/
actionFunction (request) {
actionFunction(request) {
// do action

// optional: set network specific headers
if (request.context.protocol === 'http') {
// expires in 1h
request.response.setHeader('expires', new Date(Date.now() + 3600000).toUTCString());
request.response.setHeader(
'expires',
new Date(Date.now() + 3600000).toUTCString()
);
}

// Resolve with the result content. For instance:
return Promise.resolve({acknowledge: true});
return Promise.resolve({ acknowledge: true });
}

/*
Expand All @@ -168,9 +182,9 @@ module.exports = class ControllerPlugin {
This result can be of any JS type (scalar, object, array), and
will be used to build a response to send to the requesting client
*/
otherActionFunction (request) {
otherActionFunction(request) {
// do action
return Promise.resolve(/* result content */);
}
}
};
```
5 changes: 5 additions & 0 deletions src/plugins/1/controllers/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: full.html.hbs
title: Controllers
order: 4
---
Loading