diff --git a/CHANGELOG.md b/CHANGELOG.md index 9560c1e43..d475fe259 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Added support for raiseIntent without a context via the addition of the `fdc3.nothing` context type ([#375](https://github.com/finos/FDC3/pull/375)) * Added [**FDC3 Workbench**](https://fdc3.finos.org/toolbox/fdc3-workbench/), an FDC3 API developer application ([#457](https://github.com/finos/FDC3/pull/457)) * Added advice on how to `broadcast` complex context types, composed of other types, so that other apps can listen for both the complex type and simpler constituent types ([#464](https://github.com/finos/FDC3/pull/464)) +* Added the ability to return data from an intent, via the addition of an IntentHandler type and a `getResult()` to IntentResolution, both of which return a Promise of a Context object. ([#495](https://github.com/finos/FDC3/pull/495)) * Added error `UserCancelled` to the `ResolveError` enumeration to be used when user closes the resolver UI or otherwise cancels resolution of a raised intent ([#522 ](https://github.com/finos/FDC3/pull/522)) * Added an `instanceId` (and optional `instanceMetadata`) field to `AppMetadata` allowing it to refer to specific app instances and thereby supporting targetting of intents to specific app instances. Also added a `findInstanes()` function to the desktop agent. ([#509]((https://github.com/finos/FDC3/pull/509)) * Added a References and Bibliography section to the Standard's documentation to hold links to 'normative references' and other documentation that is useful for understanding the standard ([#530](https://github.com/finos/FDC3/pull/530)) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index d576a1bc6..e04552a2b 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -31,7 +31,7 @@ interface DesktopAgent { findIntentsByContext(context: Context): Promise>; raiseIntent(intent: string, context: Context, app?: TargetApp): Promise; raiseIntentForContext(context: Context, app?: TargetApp): Promise; - addIntentListener(intent: string, handler: ContextHandler): Promise; + addIntentListener(intent: string, handler: IntentHandler): Promise; // channels getOrCreateChannel(channelId: string): Promise; @@ -75,27 +75,39 @@ const contactListener = await fdc3.addContextListener('fdc3.contact', contact => #### See also * [`Listener`](Types#listener) * [`Context`](Types#context) +* [`ContextHandler`](Types#contexthandler) ### `addIntentListener` ```ts -addIntentListener(intent: string, handler: ContextHandler): Promise; +addIntentListener(intent: string, handler: IntentHandler): Promise; ``` - Adds a listener for incoming Intents from the Agent. + Adds a listener for incoming Intents from the Agent. The handler function may return void or a promise that should resolve to a context object representing any data that should be returned to the app that raised the intent. If an error is thrown by the handler function, the promise returned is rejected, or a promise is not returned then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution`. #### Examples ```js -const listener = await fdc3.addIntentListener('StartChat', context => { - // start chat has been requested by another application +//Handle a raised intent +const listener = fdc3.addIntentListener('StartChat', context => { + // start chat has been requested by another application + return; +}); + +//Handle a raised intent and return Context data via a promise +fdc3.addIntentListener("CreateOrder", (context) => { + return new Promise((resolve) => { + // go create the order + resolve({type: "fdc3.order", id: { "orderId": 1234 }}); + }); }); ``` #### See also * [`Listener`](Types#listener) * [`Context`](Types#context) +* [`IntentHandler`](Types#intenthandler) @@ -443,7 +455,7 @@ Alternatively, the specific app or app instance to target can also be provided. If you wish to raise an intent without a context, use the `fdc3.nothing` context type. This type exists so that apps can explicitly declare support for raising an intent without context. -Returns an `IntentResolution` object with details of the app instance that was selected (or started) to respond to the intent. +Returns an `IntentResolution` object with details of the app that was selected to respond to the intent. If the application that resolves the intent returns a promise of Context data, this may be retrieved via the `getResult()` function of the IntentResolution object. If an error occurs (i.e. an error is thrown by the handler function, the promise it returns is rejected, or a promse is not returned by the handler function) then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution` with a string from the `DataError` enumeration. If a target app for the intent cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration is returned. If a specific target `app` parameter was set, but either the app or app instance is not available then the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` errors MUST be returned. @@ -451,7 +463,7 @@ If a target app for the intent cannot be found with the criteria provided or the ```js // raise an intent for resolution by the desktop agent -// a resolver UI may be displayed, or another method of resolving the intent to a +// a resolver UI may be displayed, or another method of resolving the intent to a // target applied, if more than one application can resolve the intent await fdc3.raiseIntent("StartChat", context); @@ -463,6 +475,15 @@ await fdc3.raiseIntent("StartChat", context, appIntent.apps[0]); //Raise an intent without a context by using the null context type await fdc3.raiseIntent("StartChat", {type: "fdc3.nothing"}); + +//Raise an intent and retrieve data from the IntentResolution +let resolution = await agent.raiseIntent("intentName", context); +try { + const result = await resolution.getResult(); + console.log(`${resolution.source} returned ${JSON.stringify(result)}`); +} catch(error) { + console.error(`${resolution.source} returned a data error: ${error}`); +} ``` #### See also * [`Context`](Types#context) @@ -483,7 +504,7 @@ Alternatively, the specific app or app instance to target can also be provided, Using `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app. -Returns an `IntentResolution` object with a handle to the app that responded to the selected intent. +Returns an `IntentResolution` object with details of the app that was selected to respond to the intent. If the application that resolves the intent returns a promise of Context data, this may be retrieved via the `getResult()` function of the IntentResolution object. If an error occurs (i.e. an error is thrown by the handler function, the promise it returns is rejected, or a promse is not returned by the handler function) then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution` with a string from the `DataError` enumeration. If a target app for the intent cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration is returned. If a specific target `app` parameter was set, but either the app or app instance is not available then the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` errors MUST be returned. diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index 2aa7f8749..86e0c8c1a 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -41,6 +41,22 @@ Contains constants representing the errors that can be encountered when calling * [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent) * [`DesktopAgent.raiseIntentForContext`](DesktopAgent#raiseintentforcontext) +## `DataError` + +```typescript +enum DataError { + NoDataReturned = 'NoDataReturned', + IntentHandlerRejected = 'IntentHandlerRejected', +} +``` + +Contains constants representing the errors that can be encountered when calling the [`getResult`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object. + +#### See also +* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener) +* [`DesktopAgent.raiseIntent`](DesktopAgent#raiseintent) +* [`IntentResolution`](Metadata#intentresolution) + ## `ChannelError` ```typescript diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index a5bee32f1..43bf40dd9 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -161,15 +161,20 @@ interface IntentResolution { * chose in response to `fdc3.raiseIntentForContext()`. */ readonly intent: string; - /** - * @deprecated not assignable from intent listeners - */ - readonly data?: object; /** * The version number of the Intents schema being used. */ readonly version?: string; - + /** + * Retrieves a promise that will resolve to data returned by the + * application that resolves the raised intent. If an error occurs + * (i.e. an error is thrown by the handler function, the promise + * returned by the handler function is rejected, or no promise is + * returned) then the Desktop Agent MUST reject the promise + * returned by the `getResult()` function of the `IntentResolution` + * with a string from the `DataError` enumeration. + */ + getResult(): Promise; } ``` @@ -177,8 +182,8 @@ IntentResolution provides a standard format for data returned upon resolving an #### Examples ```js -// resolve a "Chain" type intent -let resolution = await fdc3.raiseIntent("intentName", context); +//resolve a "Chain" type intent +let resolution = await agent.raiseIntent("intentName", context); // Use metadata about the resolving app instance to target a further intent try { @@ -189,6 +194,15 @@ try { await agent.raiseIntent("UpdateOrder", context, resolution.source); } catch (err) { ... } + +//resolve a "Client-Service" type intent with a data response +let resolution = await agent.raiseIntent("intentName", context); +try { + const result = await resolution.getResult(); + console.log(`${resolution.source} returned ${JSON.stringify(result)}`); +} catch(error) { + console.error(`${resolution.source} returned an error: ${error}`); +} ``` #### See also diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 19fc43314..365bcc3f9 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -41,14 +41,28 @@ type ContextHandler = (context: Context) => void; Describes a callback that handles a context event. -Used when attaching listeners for context broadcasts and raised intents. +Used when attaching listeners for context broadcasts. #### See also * [`Context`](#context) -* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener) * [`DesktopAgent.addContextListener`](DesktopAgent#addcontextlistener) * [`Channel.addContextListener`](Channel#addcontextlistener) +## `IntentHandler` + +```typescript +type IntentHandler = (context: Context) => Promise | void; +``` + +Describes a callback that handles a context event and may return a promise of a Context object to be returned to the application that raised the intent. + +Used when attaching listeners for raised intents. + +#### See also +* [`Context`](#context) +* [`DesktopAgent.addIntentListener`](DesktopAgent#addintentlistener) +* [`Channel.addContextListener`](Channel#addcontextlistener) + ## `Listener` A Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](#addintentlistener) or [`addContextListener`](#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object. diff --git a/docs/api/spec.md b/docs/api/spec.md index 0294969c3..068142a14 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -42,7 +42,7 @@ The global `window.fdc3` must only be available after the API is ready to use. T ```js function fdc3Stuff() { - // Make some fdc3 API calls here + // Make fdc3 API calls here } if (window.fdc3) { @@ -99,12 +99,14 @@ Intents provide a way for an app to request functionality from another app and d - **Remote API**: An app wants to remote an entire API that it owns to another App. In this case, the API for the App cannot be standardized. However, the FDC3 API can address how an App connects to another App in order to get access to a proprietary API. #### Intents and Context -When raising an intent a specific context may be provided. The type of the provided context may determine which applications can resolve the intent. +When raising an intent a specific context may be provided as input. The type of the provided context may determine which applications can resolve the intent. A context type may also be associated with multiple intents. For example, an `fdc3.instrument` could be associated with `ViewChart`, `ViewNews`, `ViewAnalysis` or other intents. In addition to raising a specific intent, you can raise an intent for a specific context allowing the Desktop Agent or the user (if the intent is ambiguous) to select the appropriate intent for the selected context and then to raise that intent for resolution. To raise an intent without a context, use the `fdc3.nothing` context type. This type exists so that applications can explicitly declare that they support raising an intent without a context (when registering an intent listener or in an App Directory). +An optional context object may also be returned as output by an application resolving an intent. For example, an application resolving a `CreateOrder` intent might return a context representing the order and including an ID, allowing the application that raised the intent to make further calls using that ID. + #### Intent Resolution Raising an intent will return a Promise-type object that will resolve/reject based on a number of factors. @@ -119,14 +121,6 @@ Raising an intent will return a Promise-type object that will resolve/reject bas ##### Resolution Object -> **Deprecation notice** -> -> It is not currently possible to provide a value for the `data` property described below, -as intent listeners don't currently offer a way to return values. -> -> Future versions of FDC3 plan to remove the optional `data` property from the intent resolution object, -and include a more robust mechanism for intents that need to return data back to the caller. - If the raising of the intent resolves (or rejects), a standard object will be passed into the resolver function with the following format: ```ts @@ -142,14 +136,18 @@ interface IntentResolution { * chose in response to `fdc3.raiseIntentForContext()`. */ readonly intent: string; - /** - * @deprecated not assignable from intent listeners - */ - readonly data?: object; /** * The version number of the Intents schema being used. */ readonly version?: string; + /** + * Retrieves a promise that will resolve to data returned by the application that + * resolves the raised intent. If an error occurs (i.e. an error is thrown by the handler + * function, the promise returned is rejected, or no promise is returned) then the Desktop + * Agent MUST reject the promise returned by the `getResult()` function of the + * `IntentResolution` with a string from the `DataError` enumeration. + */ + getResult(): Promise; } ``` @@ -162,7 +160,8 @@ try { catch (err){ ... } ``` -or to raise an unspecified intent for a specific context, where the user will select an intent from a resolver dialog: +or to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog: + ```js try { const resolution = await fdc3.raiseIntentForContext(context); @@ -185,6 +184,17 @@ try { catch (err) { ... } ``` +Raise an intent and retrieve data from the IntentResolution: +```js +let resolution = await agent.raiseIntent("intentName", context); +try { + const result = await resolution.getResult(); + console.log(`${resolution.source} returned ${JSON.stringify(result)}`); +} catch(error) { + console.error(`${resolution.source} returned a data error: ${error}`); +} +``` + #### Resolvers Intents functionality is dependent on resolver functionality to map the intent to a specific App. This will often require end-user input. Resolution can either be performed by the Desktop Agent (for example, by displaying a resolver UI allowing the user to pick the desired app or app instance for the intent) or by the app handling the resolution itself (by using the `findIntents` API and specifying a target app or app instance when invoking the Intent), e.g.: diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index f1d9846a6..cc3fe9b74 100644 --- a/src/api/DesktopAgent.ts +++ b/src/api/DesktopAgent.ts @@ -5,7 +5,7 @@ import { AppIntent } from './AppIntent'; import { Channel } from './Channel'; -import { ContextHandler, TargetApp } from './Types'; +import { ContextHandler, IntentHandler, TargetApp } from './Types'; import { IntentResolution } from './IntentResolution'; import { Listener } from './Listener'; import { Context } from '../context/ContextTypes'; @@ -170,26 +170,37 @@ export interface DesktopAgent { /** * Raises a specific intent for resolution against apps registered with the desktop agent. * - * The desktop agent will resolve the correct app to target based on the provided intent name and context data. If multiple matching apps are found, the user may be presented with an app picker. + * The desktop agent MUST resolve the correct app to target based on the provided intent name and context data. If multiple matching apps are found, the user MAY be presented with a Resolver UI allowing them to pick one, or another method of Resolution applied to select an app. * Alternatively, the specific app or app instance to target can also be provided. A list of valid target applications and instances can be retrieved via `findIntent`. - * + * * If you wish to raise an Intent without a context, use the `fdc3.nothing` context type. This type exists so that apps can explicitly declare support for raising an intent without context. * - * Returns an `IntentResolution` object with details of the app instance that was selected (or started) to respond to the intent. + * Returns an `IntentResolution` object with details of the app instance that was selected (or started) to respond to the intent. If the application that resolves the intent returns a promise of context data, this may be retrieved via the `getResult()` function of the `IntentResolution` object. If an error occurs (i.e. an error is thrown by the handler function, the promise returned is rejected, or no promise is returned) then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution` with a string from the `DataError` enumeration. * - * If a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the `ResolveError` enumeration is returned. + * If a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the `ResolveError` enumeration MUST be returned. * * ```javascript * // raise an intent for resolution by the desktop agent - * // a resolver UI will be displayed if more than one application can resolve the intent + * // a resolver UI may be displayed if more than one application can resolve the intent * await fdc3.raiseIntent("StartChat", context); + * * // or find apps to resolve an intent to start a chat with a given contact * const appIntent = await fdc3.findIntent("StartChat", context); * // use the metadata of an app or app instance to describe the target app for the intent * await fdc3.raiseIntent("StartChat", context, appIntent.apps[0]); + * * //Raise an intent without a context by using the null context type * await fdc3.raiseIntent("StartChat", {type: "fdc3.nothing"}); + * + * //Raise an intent and retrieve data from the IntentResolution + * let resolution = await agent.raiseIntent("intentName", context); + * try { + * const result = await resolution.getResult(); + * console.log(`${resolution.source} returned ${JSON.stringify(result)}`); + * } catch(error) { + * console.error(`${resolution.source} returned a data error: ${error}`); + * } * ``` */ raiseIntent(intent: string, context: Context, app?: TargetApp): Promise; @@ -198,11 +209,11 @@ export interface DesktopAgent { * Finds and raises an intent against apps registered with the desktop agent based purely on the type of the context data. * * The desktop agent SHOULD first resolve to a specific intent based on the provided context if more than one intent is available for the specified context. This MAY be achieved by displaying a resolver UI. It SHOULD then resolve to a specific app to handle the selected intent and specified context. - * Alternatively, the specific app or app instance to target can also be provided, in which case the resolver should only offer intents supported by the specified application. + * Alternatively, the specific app or app instance to target can also be provided, in which case the resolver SHOULD only offer intents supported by the specified application. * * Using `raiseIntentForContext` is similar to calling `findIntentsByContext`, and then raising an intent against one of the returned apps, except in this case the desktop agent has the opportunity to provide the user with a richer selection interface where they can choose both the intent and target app. * - * Returns an `IntentResolution` object with a handle to the app that responded to the selected intent. + * Returns an `IntentResolution` object with details of the app that was selected to respond to the intent. If the application that resolves the intent returns a promise of Context data, this may be retrieved via the `getResult()` function of the IntentResolution object. If an error occurs (i.e. an error is thrown by the handler function, the promise returned is rejected, or no promise is returned) then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution` with a string from the `DataError` enumeration. * * If a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the `ResolveError` enumeration is returned. * @@ -216,9 +227,30 @@ export interface DesktopAgent { raiseIntentForContext(context: Context, app?: TargetApp): Promise; /** - * Adds a listener for incoming Intents from the Agent. + * Adds a listener for incoming Intents from the Agent. The handler function may + * return void or a promise that should resolve to a context object representing + * any data that should be returned to app that raised the intent. If an error occurs + * (i.e. an error is thrown by the handler function, the promise returned is rejected, or + * a promise is not returned) then the Desktop Agent MUST reject the promise returned + * by the `getResult()` function of the `IntentResolution`. + * + * ```javascript + * //Handle a raised intent + * const listener = fdc3.addIntentListener('StartChat', context => { + * // start chat has been requested by another application + * return; + * }); + * + * //Handle a raised intent and return Context data via a promise + * fdc3.addIntentListener("CreateOrder", (context) => { + * return new Promise((resolve) => { + * // go create the order + * resolve({type: "fdc3.order", id: { "orderId": 1234}}); + * }); + * }); + * ``` */ - addIntentListener(intent: string, handler: ContextHandler): Promise; + addIntentListener(intent: string, handler: IntentHandler): Promise; /** * Adds a listener for incoming context broadcast from the Desktop Agent. diff --git a/src/api/Errors.ts b/src/api/Errors.ts index 451db0963..b83f2e351 100644 --- a/src/api/Errors.ts +++ b/src/api/Errors.ts @@ -19,6 +19,11 @@ export enum ResolveError { TargetInstanceUnavailable = 'TargetInstanceUnavailable', } +export enum DataError { + NoDataReturned = 'NoDataReturned', + IntentHandlerRejected = 'IntentHandlerRejected', +} + export enum ChannelError { NoChannelFound = 'NoChannelFound', AccessDenied = 'AccessDenied', diff --git a/src/api/IntentResolution.ts b/src/api/IntentResolution.ts index fd6411c38..b66a9390a 100644 --- a/src/api/IntentResolution.ts +++ b/src/api/IntentResolution.ts @@ -3,6 +3,7 @@ * Copyright 2019 FINOS FDC3 contributors - see NOTICE file */ +import { Context } from '../context/ContextTypes'; import { AppMetadata } from './AppMetadata'; /** @@ -10,10 +11,19 @@ import { AppMetadata } from './AppMetadata'; * ```javascript * //resolve a "Chain" type intent * let resolution = await agent.raiseIntent("intentName", context); - * //resolve a "Client-Service" type intent with data response - * let resolution = await agent.raiseIntent("intentName", context); - * var dataR = intentR.data; * + * //resolve a "Client-Service" type intent with a data response + * let resolution = await agent.raiseIntent("intentName", context); + * try { + * const result = await resolution.getResult(); + * if (result) { + * console.log(`${resolution.source} returned ${JSON.stringify(result)}`); + * } else { + * console.error(`${resolution.source} didn't return data` + * } + * } catch(error) { + * console.error(`${resolution.source} returned an error: ${error}`); + * } * // Use metadata about the resolving app instance to target a further intent * await agent.raiseIntent("intentName", context, resolution.source); * @@ -31,12 +41,16 @@ export interface IntentResolution { * chose in response to `fdc3.raiseIntentForContext()`. */ readonly intent: string; - /** - * @deprecated not assignable from intent listeners - */ - readonly data?: object; /** * The version number of the Intents schema being used. */ readonly version?: string; + /** + * Retrieves a promise that will resolve to data returned by the + * application that resolves the raised intent. The promise MUST + * reject with a string from the `DataError` enumeration if an error + * is thrown by the intent handler, it rejects the returned promise, + * or it does not return a promise. + */ + getResult(): Promise; } diff --git a/src/api/Methods.ts b/src/api/Methods.ts index 56289da38..a616f6dee 100644 --- a/src/api/Methods.ts +++ b/src/api/Methods.ts @@ -1,4 +1,13 @@ -import { AppIntent, Channel, Context, ContextHandler, IntentResolution, Listener, ImplementationMetadata } from '..'; +import { + AppIntent, + Channel, + Context, + ContextHandler, + IntentHandler, + IntentResolution, + Listener, + ImplementationMetadata, +} from '..'; import { TargetApp } from './Types'; const DEFAULT_TIMEOUT = 5000; @@ -71,7 +80,7 @@ export function raiseIntentForContext(context: Context, app?: TargetApp): Promis return rejectIfNoGlobal(() => window.fdc3.raiseIntentForContext(context, app)); } -export function addIntentListener(intent: string, handler: ContextHandler): Promise { +export function addIntentListener(intent: string, handler: IntentHandler): Promise { return rejectIfNoGlobal(() => window.fdc3.addIntentListener(intent, handler)); } diff --git a/src/api/Types.ts b/src/api/Types.ts index 4965f8e88..d1ab34bdf 100644 --- a/src/api/Types.ts +++ b/src/api/Types.ts @@ -6,5 +6,24 @@ import { AppMetadata } from '..'; import { Context } from '../context/ContextTypes'; +/** + * Operations that target apps (like open or raiseIntent) can identify + * an app just by by its name, or pass full app metadata, giving the + * desktop agent more information about the targeted app. + */ export type TargetApp = string | AppMetadata; +/** + * Describes a callback that handles a context event. + * Used when attaching listeners for context broadcasts. + */ export type ContextHandler = (context: Context) => void; +/** + * Describes a callback that handles a context event and may return a + * promise of a Context object to be returned to the application that + * raised the intent. Any response other than Promise indicates that + * the handler does not return data (which will result in the Desktop + * Agent rejecting the IntentResolution.getData() promise with the + * appropriate error message). + * Used when attaching listeners for raised intents. + */ +export type IntentHandler = (context: Context) => Promise | void;