How to develop a remote plugin?
This guide explains how a remote plugin communicates with Thymian over WebSockets via the plugin @thymian/websocket-proxy. The WebSocket server mirrors the ThymianEmitter API, i.e.:
emit(event, payload)↔ message{ "type": "emit", ... }emitAction(name, payload, options)↔ message{ "type": "emitAction", ... }with responseemitActionResult/emitActionErroron(event, handler)↔ server sends{ "type": "event", ... }onAction(name, handler)↔ server sends{ "type": "action", ... }, the client must answer withactionReplyoractionError
See also ThymianEmitter in @thymian/core — this protocol exposes the same surface over WebSockets.
Connection and handshake
Section titled “Connection and handshake”Before a connection can be established, the client must register to the server via a three-way handshake.
-
Connect to WebSocket:
ws://<host>:<port>(default port is 51234). -
Register:
-
Client sends once:
{type: 'register',token: 's3cr3t', // optional, shared secretname: 'remote-plugin', // name of the pluginonActions: ['core.run'], // only the actions listed here will be forwardedonEvents: ['core.report'], // ...same for events}This initial message starts the handshake. It tells the websocket server which plugin tries to connect and which events and actions it wants to receive.
-
Server replies with:
{type: 'register-ack',ok: true,config: { feature: true, threshold: 3 },}The server acknowledges the registration and returns the configuration of the plugin. If the provided token is invalid or if the plugin name is already taken, the server responds with
ok: false.
-
-
Send ready: After a successful
register-ack, the client sends:{ type: 'ready' }The client should send this message AFTER its configuration is done and the plugin is ready to receive events and actions.
After the handshake, the client can emit and receive events and actions. Therefore, the API of the ThymianEmitter is mirrored. In the following, the message types and their use cases are explained.
Each message uses the JSON format and always has a type property, that describes the type of the message.
Emit an event
Section titled “Emit an event”To emit an event, the client must send a EmitEventMessage with the following properties:
type: must be"emit"name: the name of the event to emitpayload: the payload of the event
An example:
{ type: 'emit', name: 'core.report', payload: { topic: 'my topic', },}Emit an action
Section titled “Emit an action”To emit an action, the client must send a EmitActionMessage with the following properties:
type: must be"emitAction"id: a unique identifier for the action (a UUID is recommended)
name: the name of the action to emitpayload: the payload of the actionoptions: optional object with the following properties:strategy:"first"(default) or"collect"to collect all replies and"deep-merge"to merge all replies into a single payloadtimeout: timeout in milliseconds that is waited for replies
An example:
{ type: 'emitAction', id: 'C4A22DA0-FDD7-4864-A731-5CBFA1A49834', name: 'core.run', payload: {}, options: { strategy: 'deep-merge', timeout: 10000, },}The plugin will receive a response to the action with either emitActionResult or emitActionError message.
Responding to an action
Section titled “Responding to an action”To respond to an action, the server must send an ActionReplyMessage with the following properties:
type: must be"actionReply"correlationId: theidof the action that was emittedname: the name of the action that was emittedpayload: the payload of the reply
Sending an error reply to an action
Section titled “Sending an error reply to an action”To send an error reply to an action, the server must send an ActionErrorMessage with the following properties:
type: must be"actionError"correlationId: theidof the action that was emittedname: the name of the action that was emittederror: an object with the following properties:name: the name of the error (optional)message: the error message (required)options: additional options (optional)
Receiving an event
Section titled “Receiving an event”When the plugin receives an event, the server sends a EventMessage with the following properties:
type: must be"event"name: the name of the eventpayload: the payload of the event
Receiving an action
Section titled “Receiving an action”When the plugin receives an action, the server sends a ActionMessage with the following properties:
type: must be"action"name: the name of the actionpayload: the payload of the action
The client will respond to the action with either actionReply or actionError message.
Receiving a reply to an action
Section titled “Receiving a reply to an action”When the plugin receives a reply to an action, the server sends a ActionResultMessage with the following properties:
type: must be"emitActionResult"correlationId: theidof the action that was emittedname: the name of the action that was emittedpayload: the payload of the reply
Receiving an error reply to an action
Section titled “Receiving an error reply to an action”When the plugin receives an error reply to an action, the server sends a ActionErrorMessage with the following properties:
type: must be"emitActionError"correlationId: theidof the action that was emittedname: the name of the action that was emittederror: an object with the following properties:name: the name of the error (optional)message: the error message (optional)