# Intents API

Source: https://docs.interop.io/browser/capabilities/data-sharing/intents/intents-api/index.html

## Overview

The Intents API is accessible via the [`io.intents`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md) object.

## Finding Intents

To find all registered Intents, use the [`all()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-all) method:

```javascript
const allIntents = await io.intents.all();
```

To get a collection of all Intents that fit certain criteria, use the [`find()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-find) method:

```javascript
// The `find()` method resolves with a list of `Intent` objects.
const intents = await io.intents.find("ViewChart");
const viewChartIntent = intents[0];
```

The [`find()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-find) method accepts a string or an [`IntentFilter`](https://docs.interop.io/browser/reference/javascript/intents/intentfilter/index.md) object as an optional argument. The [`IntentFilter`](https://docs.interop.io/browser/reference/javascript/intents/intentfilter/index.md) object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `name` | `string` | Name of the Intent for which to search. |
| `contextType` | `string` | The type of pre-defined data structure with which the Intent handler works. |
| `resultType` | `string` | The type of pre-defined data structure which the Intent handler returns. |

If no filter is supplied, [`find()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-find) returns all registered Intents.

Available since io.Connect Browser 3.2

To get all Intents for a specific Intent handler, use the [`getIntents()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-getIntents) method and pass an [`IntentHandler`](https://docs.interop.io/browser/reference/javascript/intents/intenthandler/index.md) object as a required argument:

```javascript
const intents = await io.intents.find("ViewChart");
const handler = intents[0].handlers[0];

const result = await io.intents.getIntents(handler);
// The `getIntents()` method resolves with an object with an `intents` property holding a list of `IntentInfo` objects.
result.intents.forEach(console.log);
```

## Raising Intents

To raise an Intent, use the [`raise()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-raise) method:

```javascript
await io.intents.raise("ViewChart");
```

The [`raise()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-raise) method accepts an Intent name as a string or an [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object as a required argument. The only required property of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object is `intent` which must specify the name of the Intent to be raised.

The [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `context` | `object` | Context data that will be provided to the Intent handler. |
| `handlers` | `object[]` | Collection of Intent handlers that can be presented to the user via an Intent Resolver UI. If there isn't an Intent Resolver app available (or if the list consists of only one handler), the first member of the collection will be used as an Intent handler. |
| `intent` | `string` | Name of the Intent to raise. |
| `options` | `object` | [`ApplicationStartOptions`](https://docs.interop.io/browser/reference/javascript/app%20management/applicationstartoptions/index.md) object that will be passed to a newly started app instance, if such is to be used as an Intent handler. |
| `target` | `"startNew"` \| `"reuse"` \| `{ app?: string; instance?: string }` | Target for the raised Intent. Use `"startNew"` to start a new instance of the first available Intent handler. Use `"reuse"` to reuse the first available running instance of an Intent handler. Will fall back to `"startNew"` if there are no running instances available. Use an object with optional `app` and `instance` properties to target specific apps or app instances. The `app` property accepts an app name, the `instance` property - an ID of a running app instance. Provide a value for the `app` property to start a new instance of a specific Intent handler app. Provide a value for the `instance` property to reuse a specific running instance of an Intent handler. If both `app` and `instance` are set, `instance` will take precedence. |
| `timeout` | `number` | Interval in milliseconds to wait for the [`raise()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-raise) method to resolve when raising an Intent. Defaults to `90000`. |
| `waitUserResponseIndefinitely` | `boolean` | If `true`, the framework will wait for the user to choose a handler for the raised Intent from the Intent Resolver UI before starting the timeout specified in the `timeout` property of the Intent request. Otherwise, the timeout will start when the [`raise()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-raise) method is invoked. Defaults to `false`. |

## Filtering Intent Handlers

Available since io.Connect Browser 3.2

To retrieve available Intent handlers based on a specified criteria, use the [`filterHandlers()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-filterHandlers) method and provide a [`HandlerFilter`](https://docs.interop.io/browser/reference/javascript/intents/handlerfilter/index.md) object as a required argument. The `HandlerFilter` object allows you to specify whether the Intent Resolver UI app will open when there are more than one available Intent handlers in order to display them to the user:

```javascript
const filter = {
    intent: "ViewChart",
    openResolver: false
};

const result = await io.intents.filterHandlers(filter);

// The `filterHandlers()` method resolves with an object with a `handlers` property holding a list of `IntentHandler` objects.
result.handlers.forEach(console.log);
```

## Excluding Intent Handlers

Available since io.Connect Browser 4.2

To exclude Intent handlers from the results when using the [`filterHandlers()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-filterHandlers) method, use the `excludeList` property of the [`HandlerFilter`](https://docs.interop.io/browser/reference/javascript/intents/handlerfilter/index.md) object and pass an array of [`HandlerExclusionCriteria`](https://docs.interop.io/browser/reference/javascript/intents/handlerexclusioncriteria/index.md) as a value.

It's possible to exclude Intent handlers by app name and by app instance ID:

```javascript
const filter = {
    intent: "ViewChart",
    openResolver: false,
    // Excluding an app by its name and a running instance of another app from the Intent handler result.
    excludeList: [
        {
            // This will exclude the app, but won't exclude any running instances of it.
            applicationName: "my-app-name"
        },
        {
            // This will exclude a running instance of an app, but won't exclude the app itself.
            instanceId: "my-other-app-instance-id"
        }
    ]
};

const result = await io.intents.filterHandlers(filter);
```

## Targeting Intent Handlers

To target which apps or running instances will handle a raised Intent, you can use the `handlers` and/or `target` properties of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object.

- using the `target` property:

The `target` property allows you to specify whether a new instance of an Intent handler app is to be started, or an already running instance is to be reused for handling the Intent.

The following example demonstrates using the `target` property of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object:

```javascript
const filter = { intent: "ViewChart" };
const result = await io.intents.filterHandlers(filter);
const intentHandler = result.handlers[0];

const intentRequest = {
    intent: "ViewChart",
    target: { app: intentHandler.applicationName }
};

await io.intents.raise(intentRequest);
```

The `target` property of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object accepts the following values:

| Value | Description |
|-------|-------------|
| `"reuse"` | Will reuse the first available running instance of an Intent handler or will fall back to `"startNew"` if there are no running instances available. |
| `"startNew"` | Will start a new instance of the first available Intent handler. |
| `{ app?: string, instance?: string }` | An object with optional `app` and `instance` properties. The `app` property accepts an app name, the `instance` property - an ID of a running app instance. Provide a value for the `app` property to start a new instance of a specific Intent handler app. The app name is available in the `applicationName` property of the [`IntentHandler`](https://docs.interop.io/browser/reference/javascript/intents/intenthandler/index.md) object. Provide a value for the `instance` property to reuse a specific running instance of an Intent handler. The ID of an Intent handler instance is available in the `instanceId` property of the [`IntentHandler`](https://docs.interop.io/browser/reference/javascript/intents/intenthandler/index.md) object. If both `app` and `instance` are set, `instance` will take precedence. Using this targeting option gives you full control over the choice of an appropriate Intent handler. |

The default value for the `target` property is `"startNew"` when the Intent has been defined in an app definition. If the Intent has been [registered dynamically](#registering_intents_dynamically), the default value is `"reuse"`.

To determine whether an Intent handler is an app or an already running instance, use the `type` property of the [`IntentHandler`](https://docs.interop.io/browser/reference/javascript/intents/intenthandler/index.md) object, which will be set to `"app"` or `"instance"` respectively.

> ⚠️ *Note that in order for the running Intent handler instance to be registered as type `"instance"`, the app must use the [`register()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-register) method in its code to handle context updates (see [Handling Context Updates](#context-handling_context_updates)) or to register an Intent dynamically (see [Registering Intents Dynamically](#registering_intents_dynamically)). Otherwise, the running Intent handler instance will be of type `"app"`.*

- using the `handlers` property:

The `handlers` property allows you to pass directly an array of [`IntentHandler`](https://docs.interop.io/browser/reference/javascript/intents/intenthandler/index.md) objects to be used for handling the Intent and provides more flexibility when targeting Intent handlers. For instance, you can filter them by context type or result type before attaching them to the Intent request:

```javascript
const filter = { intent: "ViewChart" };
const result = await io.intents.filterHandlers(filter);
// Filtering the handlers by context type.
const handlers = result.handlers.filter(handler => handler.contextTypes.includes("Instrument"));

const intentRequest = {
    intent: "ViewChart",
    handlers
};

await io.intents.raise(intentRequest);
```

- using a combination of both properties:

When using the `target` and `handlers` properties of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object in a combination, you must take into consideration that the `target` property takes precedence over the `handlers` property.

The following table demonstrates what the resulting behavior would be for various combinations between the `target` and `handlers` properties:

| Value/App/Instance for `target` | Apps/Instances for `handlers` | Targeted Intent Handler |
|---------------------------------|-------------------------------|-------------------------|
| `undefined` | App-A, App-B | New instance of App-A |
| `undefined` | App-A, App-B, Instance-A, Instance-B | Reuse Instance-A |
| `"reuse"` | App-A, App-B | New instance of App-A |
| `"reuse"` | App-A, App-B, Instance-A, Instance-B | Reuse Instance-A |
| `"startNew"` | App-A, App-B | New instance of App-A |
| `"startNew"` | App-A, App-B, Instance-A, Instance-B | New instance of App-A |
| `{ app: "App-A" }` | App-A, App-B | New instance of App-A |
| `{ app: "App-A" }` | App-A, App-B, Instance-A, Instance-B | New instance of App-A |
| `{ app: "App-A" }` | App-B, Instance-A, Instance-B | New instance of App-A |
| `{ instance: "Instance-B" }` | App-A, App-B, Instance-A, Instance-B | Reuse Instance-B |
| `{ instance: "Instance-B" }` | App-A, App-B, Instance-A | Reuse Instance-B if such is found within the io.Connect framework and it's registered as an Intent handler, otherwise - throw an error. |

## Clearing Saved Intent Handlers

Available since io.Connect Browser 3.4

To clear all previously [saved Intent handlers](https://docs.interop.io/browser/capabilities/data-sharing/intents/overview/index.md#extending_the_intent_resolver-intent_resolver_api-saving_intent_handlers), use the [`clearSavedHandlers()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-clearSavedHandlers) method of the Intents API. To remove a saved handler for a specific Intent, use the `clearSavedHandler` property of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object when raising the Intent:

```javascript
const intentRequest = {
    name: "ViewChart",
    // Clearing a previously saved handler for this Intent.
    clearSavedHandler: true
};

await io.intents.raise(intentRequest);

// Clearing all saved handlers for all previously raised Intents.
await io.intents.clearSavedHandlers();
```

## Context

### Passing Initial Context

To pass initial context to the Intent handler, use the `context` property of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object. It accepts an [`IntentContext`](https://docs.interop.io/browser/reference/javascript/intents/intentcontext/index.md) object as a value:

```javascript
const intentRequest = {
    intent: "ViewChart",
    target: "startNew",
    context: {
        type: "Instrument",
        data: {
            // Context for the started app.
            RIC: "MSFT"
        }
    },
    // Specify app start options for the Intent handler.
    options: {
        width: 300,
        height: 200
    }
};

await io.intents.raise(intentRequest);
```

The `type` property of the [`IntentContext`](https://docs.interop.io/browser/reference/javascript/intents/intentcontext/index.md) object is required and specifies the structure of the context object. The `data` property is the actual data to be passed to the Intent handler.

The `options` property of the [`IntentRequest`](https://docs.interop.io/browser/reference/javascript/intents/intentrequest/index.md) object is used to pass custom [`ApplicationStartOptions`](https://docs.interop.io/browser/reference/javascript/app%20management/applicationstartoptions/index.md) to the Intent handler.

### Handling Context Updates

To handle the context data passed when an Intent is raised and targeted at your app, use the [`register()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-register) method. It accepts two required arguments - an Intent name and a context handler definition:

```javascript
const intentName = "ViewChart";

// Context handler definition.
function contextHandler (context) {
    // Check the context type.
    const contextType = context.type;

    if (contextType === "Instrument") {
        // Extract the context data.
        const data = context.data;
        // App-specific logic for handling the new context data.
    };
};

await io.intents.register(intentName, contextHandler);
```

## Registering Intents Dynamically

To register an Intent dynamically, use the [`register()`](https://docs.interop.io/browser/reference/javascript/intents/api/index.md#API-register) method. Besides an Intent name, this method also accepts an object describing an Intent as a first required argument:

```javascript
// Intent definition.
const intent = {
    intent: "ViewChart",
    contextTypes: ["Instrument"],
    displayName: "Fidessa Instrument Chart",
    icon: "https://example.com/resources/icon.ico"
};

// Context handler.
function contextHandler (context) {
    // Check the context type.
    const contextType = context.type;

    if (contextType === "Instrument") {
        // Extract the context data.
        const data = context.data;
        // App-specific logic for handling the new context data.
    };
};

await io.intents.register(intent, contextHandler);
```

> ⚠️ *Note that when you register an Intent dynamically and the Intent isn't [defined in an app definition](https://docs.interop.io/browser/capabilities/data-sharing/intents/overview/index.md#defining_intents), your app must be running in order to handle the Intent, and it will always be of type `"instance"`. If your app isn't running when this Intent is raised, it won't be available as a possible Intent handler.*

## API Reference

For a complete list of the available Intents API methods and properties, see the [Intents API Reference Documentation](https://docs.interop.io/browser/reference/javascript/intents/api/index.md).
