Interception
Overview
Available since io.Connect Desktop 9.6
The Interception API is accessible via the io.interception
object.
Registering Interception Handlers
For your app to be able to register interception handlers, you must enable interception from the system configuration of io.Connect Desktop.
⚠️ Note that only a single interception handler can be registered per operation within an API domain.
To register an interception handler, use the register()
method and provide an InterceptionRegistrationConfig
object as a required argument. Use this object to specify which io.Connect API domains and operations within them to intercept, as well as to provide a handler function that will be invoked when the targeted operation has been intercepted.
The interception handler will receive an InterceptionMessage
object as an argument, which you can use to extract data about the intercepted operation.
The InterceptionMessage
object has the following properties:
Property | Type | Description |
---|---|---|
callerId |
string |
ID of the app that has invoked the platform operation. Can be used for tracking purposes. |
domain |
string |
The io.Connect API domain in which the platform operation has been intercepted. |
operation |
string |
The io.Connect platform operation that has been intercepted. |
operationArgs |
any[] |
In the "before" phase, this property will contain the arguments with which the calling app has invoked the intercepted operation. In the "after" phase, this property will contain the result returned from executing the default platform implementation of the intercepted operation (or the result from the decorated operation, if the interception handler was invoked also in the "before" phase to modify the default operation). |
phase |
"before" | "after" |
Specifies whether the platform operation has been intercepted before or after the execution of its default implementation. |
The handler may return an InterceptionResponse
object or undefined
(for details on how the value returned from the interception handler affects the intercepted operation, see the Interception Phases section).
The following example demonstrates how to register an interception handler for the "raise"
operation of the Intents API domain (invoked by the raise()
method of the Intents API). The handler will be invoked during both interception phases - before and after the default platform implementation of the intercepted operation has been executed. In the "before"
phase, the context data in the IntentRequest
object with which the Intent was originally raised will be modified. In the "after"
phase, the result in the IntentResult
object returned from executing the default platform operation will be modified:
// Specify which API domains and which operations within them to intercept.
const interceptions = [
{
domain: "intents",
operation: "raise"
// If an interception phase isn't explicitly specified here, the handler
// will be invoked during both interception phases - before and after the default
// platform implementation of the intercepted operation has been executed.
}
];
// Handler that will be invoked when the targeted platform operation has been intercepted.
// The handler will receive as an argument an `InterceptionMessage` object describing the intercepted operation.
const handler = (message) => {
const phase = message.phase;
// Defining the behavior of the handler based on the current interception phase.
if (phase === "before") {
// Extracting the `IntentRequest` object with which the Intent was originally raised.
let raiseIntentArgs = message.operationArgs[0];
// Modifying the context data with which to raise the Intent.
raiseIntentArgs.context.data = { io: 42 };
// The modified operation arguments must be returned as an `InterceptionResponse` object with an `operationArgs` property.
const modifiedArgs = { operationArgs: [raiseIntentArgs] };
// The execution of the default platform implementation will proceed with the modified arguments.
return modifiedArgs;
};
if (phase === "after") {
// Extracting the `IntentResult` object returned from executing
// the default platform implementation for raising an Intent.
let raiseIntentResult = message.operationArgs[0];
// Modifying the `IntentResult` object.
raiseIntentResult.context.data = { io: 42 };
// The modified operation result must be returned as an `InterceptionResponse` object with an `operationResult` property.
const modifiedResult = { operationResult: raiseIntentResult };
return modifiedResult;
};
};
// Configuration for registering an interception handler.
const config = { interceptions, handler };
// Registering an interception handler.
await io.interception.register(config);
Unregistering Interception Handlers
You can register only a single interception handler per operation within an API domain. If you want to register another interception handler for the same operation within the same API domain, you must first unregister the already existing one.
To unregister an interception handler, use the unregister()
method and provide an InterceptionUnregistrationConfig
object as a required argument.
The following example demonstrates how to unregister an interception handler for the "raise"
operation of the Intents API domain:
const config = {
interceptions: [
{
domain: "intents",
operation: "raise"
}
]
};
await io.interception.unregister(config);
Interception Phases
The io.Connect API domain operations can be intercepted both before and after executing their default implementation. This enables you to have full control over the API domain operations: you can modify the operation arguments, prevent the execution of the default implementation, and modify the result returned from the default implementation.
Interception handlers can target a specific interception phase, or they can be invoked during both phases. To specify a phase during which to invoke the interception handler, use the phase
property of the Interception
object when defining an API domain operation to intercept. The phase
accepts "before"
, "after"
, or "all"
(default) as a value.
The following example demonstrates how to register an interception handler that will only be invoked in the phase before the default platform implementation of the intercepted operation has been executed:
const config = {
interceptions: [
{
domain: "intents",
operation: "raise",
phase: "before"
}
],
handler: (message) => {
console.log(`Interception phase: ${message.phase}`);
}
};
await io.interception.register(config);
Before Phase
The "before"
phase allows you to modify the arguments for the intercepted operation, and to proceed with or prevent the execution of the default platform implementation of the operation.
Modifying the Operation Arguments
The interception handler has access to the operation arguments via the operationArgs
array of the InterceptionMessage
object that it receives as an argument. You can use this array to extract the operation arguments and modify them. You can modify and return from the interception handler directly the InterceptionMessage
object, or you can return only the modified arguments in an InterceptionResponse
object by using its operationArgs
property.
⚠️ Note that the
operationArgs
property of theInterceptionResponse
object is taken into account only during the"before"
phase.
The following example demonstrates how to modify the argument (an IntentRequest
object) for the "raise"
operation of the Intents API domain in the "before"
phase:
const handler = (message) => {
const phase = message.phase;
if (phase === "before") {
// Extracting the `IntentRequest` object with which the Intent was originally raised.
let raiseIntentArgs = message.operationArgs[0];
// Modifying the context data with which to raise the Intent.
raiseIntentArgs.context.data = { io: 42 };
// The modified operation arguments must be returned as an `InterceptionResponse` object with an `operationArgs` property.
const modifiedArgs = { operationArgs: [raiseIntentArgs] };
// The execution of the default platform implementation will proceed with the modified arguments.
return modifiedArgs;
};
};
Preventing the Execution of the Default Operation Implementation
To prevent the execution of the default implementation of the intercepted platform operation, use the operationResult
property of the InterceptionResponse
object to return an operation result directly from the interception handler in the "before"
phase:
const handler = (message) => {
const phase = message.phase;
if (phase === "before") {
// The operation result must be returned as an `InterceptionResponse` object with an `operationResult` property.
const result = { operationResult: { io: 42 } };
// Returning a result will prevent the execution of
// the default implementation of the intercepted operation.
return result;
};
};
Proceeding with the Default Operation Implementation
To instruct the platform to proceed with the default implementation of the intercepted operation, return undefined
from the interception handler in the "before"
phase:
const handler = (message) => {
const phase = message.phase;
if (phase === "before") {
// This will instruct the platform to proceed with
// the default implementation of the intercepted operation.
return;
};
};
After Phase
The "after"
phase allows you to modify the result returned from executing the default platform implementation of the intercepted operation, or the result from the decorated operation, if the interception handler was invoked also in the "before"
phase to modify the default operation. You can also choose to return directly the already calculated result without modifying it.
Modifying the Operation Result
The interception handler has access to the already calculated result via the operationArgs
array of the InterceptionMessage
object that it receives as an argument. You can use this array to extract the operation result and modify it. You must return the modified result in an InterceptionResponse
object by using its operationResult
property.
The following example demonstrates how to modify the result (an IntentResult
object) from the "raise"
operation of the Intents API domain in the "after"
phase:
const handler = (message) => {
const phase = message.phase;
if (phase === "after") {
// Extracting the `IntentResult` object returned from executing
// the default platform implementation for raising an Intent.
let raiseIntentResult = message.operationArgs[0];
// Modifying the `IntentResult` object.
raiseIntentResult.context.data = { io: 42 };
// The modified operation result must be returned as an `InterceptionResponse` object with an `operationResult` property.
const modifiedResult = { operationResult: raiseIntentResult };
return modifiedResult;
};
};
Returning the Already Calculated Result
To return the already calculated result for the intercepted operation without modifying it, return undefined
from the interception handler in the "after"
phase:
const handler = (message) => {
const phase = message.phase;
if (phase === "after") {
// This will instruct the platform to return
// the already calculated result for the intercepted operation.
return;
};
};
Domains & Operations
This section describes the io.Connect API domain and operation IDs, and the shape of the operation arguments and results each operation expects in order to be executed.
⚠️ Note that, currently, it's possible to intercept control message only for the
"raise"
operation of the Intents API domain.
Intents
To send a control message to the Intents domain, set the domain
property of the Interception
object to "intents"
.
The following io.Connect operations are available for this domain:
"raise"
Raises an Intent.
The argument for this operation is an IntentRequest
object.
Returns an IntentResult
object.
Reference
For a complete list of the available Interception API methods and properties, see the Interception API Reference Documentation.