Plugins
Overview
All Browser Client apps (including the Main app, which in a way is also a Browser Client) use the io.Connect functionalities provided by the io.Connect APIs by sending messages to the @interopio/browser-platform
library in the Main app. These control messages contain specific information about the requested io.Connect operations which the library processes, and executes the respective commands in the respective io.Connect API domains. Therefore, by using Plugins it's possible to intercept such an operation request on a lower level in order to decorate the default functionality, cancel it, or replace it with your custom functionality.
For a full example, see the Interception Example section and the source code of the Main app in the io.Connect Browser Seed Project.
Registering Interception Requests
To register an interception request, you must use the interception
property of the platform
object provided as a third argument to your Plugin implementation. The platform
object has the following properties:
Property | Type | Description |
---|---|---|
interception |
object |
An object that can be used for registering interception requests. |
system |
object |
An object that can be used for sending control messages to the different io.Connect domains in order to execute various io.Connect operations. See Manipulating Default Operations. |
logger |
object |
An io.Connect Logger API that can be used for logging. |
platformApi |
object |
An object that currently contains only version strings for the io.Connect Browser the platform. |
The interception
object has the following properties:
Property | Type | Description |
---|---|---|
register |
function |
Function for registering an interception request. |
The register()
method accepts as an argument an object describing the interception request. This object has the following properties:
Property | Type | Description |
---|---|---|
callInterceptor |
function |
A function for handling the intercepted io.Connect operation. |
interceptions |
object[] |
An array of objects each containing domain and operation properties that define for which io.Connect API domain and for which io.Connect operation the interception handler will be invoked. |
Registering an interception request in an already defined Plugin:
// Handler for the intercepted io.Connect operation.
const myInterceptionHandler = async (controlMessage) => {
// The default io.Connect operation will be prevented
// and your implementation here will be executed instead.
const message = `Received control message for domain: ${controlMessage.domain}, `
+ `operation: ${controlMessage.operation}, `
+ `by caller with ID: ${controlMessage.callerId}, `
+ `of type: ${controlMessage.callerType}`;
console.log(message);
};
// Plugin implementation.
const myPluginStartFunction = async (io, config, platform) => {
// Defining an interception request.
const interceptionRequest = {
callInterceptor: myInterceptionHandler
// The handler will be executed every time a Browser Client tries to raise a notification.
interceptions: [
{ domain: "notifications", operation: "raiseNotification" }
]
};
// Registering an interception request.
await platform.interception.register(interceptionRequest);
};
The control message object received as an argument by the interception handler has the following properties:
Property | Type | Description |
---|---|---|
domain |
string |
The io.Connect API domain in which the operation has been intercepted. See Domains & Operations. |
operation |
string |
The io.Connect operation that has been intercepted. See Domains & Operations. |
data |
object |
Data for the execution of the io.Connect command. |
settings |
object |
Optional settings for executing an io.Connect operation. See Manipulating Default Operations. |
callerType |
"plugin" | "client" |
Type of the caller - either a Browser Client, or a Plugin implementation. |
callerId |
string |
ID of the caller. Can be used for tracking purposes. |
commandId |
string |
ID of the command. Can be used for tracking purposes. |
Manipulating Default Operations
Intercepting a control message allows you to decorate the default behavior of the respective operation, replace the operation with your own implementation, or entirely prevent its execution.
To replace the default operation, provide your own implementation within the interception handler. To prevent the execution of the default operation, simply return from the handler.
In order to decorate the default operation, you must use the system
property of the platform
object to invoke the default operation behavior before or after your custom logic has been executed in the interception handler.
The system
object has the following properties:
Property | Type | Description |
---|---|---|
sendControl |
function |
Function for sending control messages to the io.Connect API domains for executing specific io.Connect operations. |
The base control message that you must pass as an argument to the sendControl()
method has the following properties:
Property | Type | Description |
---|---|---|
domain |
string |
Required. The io.Connect API domain in which the operation has been intercepted. See Domains & Operations. |
operation |
string |
Required. The io.Connect operation that has been intercepted. See Domains & Operations. |
data |
object |
Data for the execution of the io.Connect command. |
settings |
object |
Optional settings for executing an io.Connect operation. |
When you invoke an io.Connect operation after you have decorated it, you must set the skipInterception
property of the optional settings
object to true
in order to avoid an infinite loop of invoking and intercepting the same operation. If you decide to invoke a different io.Connect operation than the intercepted one, it isn't necessary to set the skipInterception
flag, unless you have registered an interception handler for that operation too and want to skip it.
Decorating a default io.Connect operation:
const myInterceptionHandler = async (controlMessage, platform) => {
// This is the custom code that will be executed before the default io.Connect operation.
const message = `Received control message for domain: ${controlMessage.domain}, `
+ `operation: ${controlMessage.operation}, `
+ `by caller with ID: ${controlMessage.callerId}, `
+ `of type: ${controlMessage.callerType}`;
console.log(message);
// Invoking the default io.Connect operation by passing the necessary data
// and setting the `skipInterception` flag to `true` to avoid an infinite loop.
await platform.system.sendControl({ ...controlMessage, settings: { skipInterception: true } });
};
const myPluginStartFunction = async (io, config, platform) => {
const interceptionRequest = {
callInterceptor: (controlMessage) => myInterceptionHandler(controlMessage, platform),
interceptions: [
{ domain: "notifications", operation: "raiseNotification" }
]
};
await platform.interception.register(interceptionRequest);
};
Interception Example
The following example demonstrates how to intercept a request for raising a notification in order to decorate the default functionality:
import IOBrowserPlatform from "@interopio/browser-platform";
// Handler for the intercepted io.Connect operation.
const myInterceptionHandler = async (controlMessage, platform) => {
// This is the custom code that will be executed before the default io.Connect operation.
const message = `Received control message for domain: ${controlMessage.domain}, `
+ `operation: ${controlMessage.operation}, `
+ `by caller with ID: ${controlMessage.callerId}, `
+ `of type: ${controlMessage.callerType}`;
console.log(message);
// Invoking the default io.Connect operation by passing the necessary data
// and setting the `skipInterception` flag to `true` to avoid an infinite loop.
await platform.system.sendControl({ ...controlMessage, settings: { skipInterception: true } });
};
// Plugin implementation.
const myPluginStartFunction = async (io, config, platform) => {
// Defining an interception request.
const interceptionRequest = {
// Pass the `platform` object as an argument to the interception handler.
// The handler will be executed every time a Browser Client tries to raise a notification.
callInterceptor: (controlMessage) => myInterceptionHandler(controlMessage, platform),
interceptions: [
{ domain: "notifications", operation: "raiseNotification" }
]
};
// Registering an interception request.
await platform.interception.register(interceptionRequest);
};
// Plugin definition.
const myNotificationsPlugin = {
name: "notifications-interceptor",
start: myPluginStartFunction,
version: "1.0.0",
config: {},
critical: true
};
// Configuration for the Browser Platform library where all Plugins must be defined.
const config = {
licenseKey: "my-license-key",
plugins: {
definitions: [myNotificationsPlugin]
}
};
const { io } = await IOBrowserPlatform(config);