From 70161e4ba6b42f898a139b76544ec924040c13d1 Mon Sep 17 00:00:00 2001 From: Kris West Date: Thu, 11 Nov 2021 12:37:25 +0000 Subject: [PATCH 01/11] Added the ability to return data from a raised intent --- CHANGELOG.md | 1 + docs/api/ref/DesktopAgent.md | 24 ++++++++++++---- docs/api/ref/Metadata.md | 39 ++++++++++++++++++++------ docs/api/ref/Types.md | 18 ++++++++++-- docs/api/spec.md | 54 ++++++++++++++++++++++++------------ src/api/DesktopAgent.ts | 54 ++++++++++++++++++++++++++++++------ src/api/IntentResolution.ts | 35 ++++++++++++++++++----- src/api/Methods.ts | 13 +++++++-- src/api/Types.ts | 16 +++++++++++ 9 files changed, 202 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 874a91e42..ea1d20c82 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 `getData()` to IntentResolution, both of which return a Promise of a Context object. ([#XXX](https://github.com/finos/FDC3/pull/XXX)) ### Changed * Consolidated `Listener` documentation with other types ([#404](https://github.com/finos/FDC3/pull/404)) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index f7b52efdd..306950163 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -30,7 +30,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): Listener; + addIntentListener(intent: string, handler: IntentHandler): Listener; // channels getOrCreateChannel(channelId: string): Promise; @@ -71,27 +71,39 @@ const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... #### See also * [`Listener`](Types#listener) * [`Context`](Types#context) +* [`ContextHandler`](Types#contexthandler) ### `addIntentListener` ```ts -addIntentListener(intent: string, handler: ContextHandler): Listener; +addIntentListener(intent: string, handler: IntentHandler): Listener; ``` - 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 is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. #### Examples ```js +//Handle a raised intent const listener = fdc3.addIntentListener('StartChat', context => { - // start chat has been requested by another application + // start chat has been requested by another application + return; +}); + +//Handle a raised intent and return Context data via a promise +fdc3.addIntentListener("trade", (context) => { + return new Promise((resolve) => { + // go place trade + resolve({result: "trade placed successfully"}); + }); }); ``` #### See also * [`Listener`](Types#listener) * [`Context`](Types#context) +* [`IntentHandler`](Types#intenthandler) @@ -389,7 +401,7 @@ Alternatively, the specific app to target can also be provided. A list of valid 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 that was selected 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. If a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the [`ResolveError`](Errors#resolverrror) enumeration is returned. @@ -432,7 +444,7 @@ Alternatively, the specific app to target can also be provided, in which case an 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. If a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration is returned. diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index 10f310ad9..46ebc7fb1 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -126,21 +126,44 @@ The Interface used to describe an Intent within the platform. ```ts interface IntentResolution { - source: TargetApp; +/** + * The application that resolved the intent. + */ + readonly source: TargetApp; /** - * @deprecated not assignable from intent listeners - */ - data?: object; - version: string; + * 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 will + * reject if an error is thrown by the intent handler or the promise + * returned by the intent handler is reject. If the intent handler + * does not return a promise this function will return null. + */ + getData(): Promise | null; } ``` IntentResolution provides a standard format for data returned upon resolving an intent. -#### Example +#### Examples ```js -// resolve a "Chain" type intent -const intentResolution = await fdc3.raiseIntent("intentName", context); +//resolve a "Chain" type intent +let resolution = await agent.raiseIntent("intentName", context); + +//resolve a "Client-Service" type intent with a data response +let resolution = await agent.raiseIntent("intentName", context); +try { + const result = await resolution.getData(); + 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}`); +} ``` #### See also diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index f1d981fe8..d31940e5c 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 5c0a9b309..d8e81b0f6 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,27 +121,28 @@ 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: ```js { - source: String; - data?: Object; - version: String; + /** + * The application that resolved the intent. + */ + readonly source: TargetApp; + /** + * 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 will + * reject if an error is thrown by the intent handler or the promise + * returned by the intent handler is reject. If the intent handler + * does not return a promise this function will return null. + */ + getData(): Promise | null; } ``` -- *source* = identifier for the Application resolving the intent (null if the intent could not be resolved) -- *data* = return data structure - if one is provided for the given intent -- *version* = the version number of the Intents schema being used - For example, to raise a specific Intent: @@ -152,7 +155,7 @@ catch (er){ } ``` -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 result = await fdc3.raiseIntentForContext(context); @@ -165,6 +168,21 @@ catch (er){ } ``` +Raise an intent and retrieve data from the IntentResolution: +```js +let resolution = await agent.raiseIntent("intentName", context); +try { + const result = await resolution.getData(); + 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}`); +} +``` + #### 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 for the intent) or by the app calling App handling the resolution itself (by using the `findIntents` API) and then invoking the Intent on a specific target application, e.g.: diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index 6b449a6f6..fdde71084 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'; @@ -122,25 +122,40 @@ 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 to target can also be provided. A list of valid target applications can be retrieved via `findIntent`. * - * Returns an `IntentResolution` object with details of the app that was selected 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. * * 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. * * ```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 returned AppIntent object to target one of the returned chat apps by name * await fdc3.raiseIntent("StartChat", context, appIntent.apps[0].name); * // or use one of the AppMetadata objects returned in the AppIntent object's 'apps' array * 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.getData(); + * 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}`); + * } * ``` */ raiseIntent(intent: string, context: Context, app?: TargetApp): Promise; @@ -148,12 +163,12 @@ 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 to target can also be provided, in which case the resolver should only offer intents supported by the specified application. + * The desktop agent will 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 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. * * 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. * @@ -167,9 +182,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 is + * thrown by the handler function, or the promise returned is rejected, then the + * Desktop Agent MUST reject the promise returned by the `getData()` 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("trade", (context) => { + * return new Promise((resolve) => { + * // go place trade + * resolve({result: "trade placed successfully"}); + * }); + * }); + * ``` */ - addIntentListener(intent: string, handler: ContextHandler): Listener; + addIntentListener(intent: string, handler: IntentHandler): Listener; /** * Adds a listener for incoming context broadcast from the Desktop Agent. diff --git a/src/api/IntentResolution.ts b/src/api/IntentResolution.ts index b2fc05eef..205818519 100644 --- a/src/api/IntentResolution.ts +++ b/src/api/IntentResolution.ts @@ -3,23 +3,44 @@ * Copyright 2019 FINOS FDC3 contributors - see NOTICE file */ +import { Context } from '../context/ContextTypes'; import { TargetApp } from './Types'; /** * IntentResolution provides a standard format for data returned upon resolving an intent. * ```javascript * //resolve a "Chain" type intent - * var intentR = await agent.raiseIntent("intentName", context); - * //resolve a "Client-Service" type intent with data response - * var intentR = await agent.raiseIntent("intentName", context); - * var dataR = intentR.data; + * let resolution = await agent.raiseIntent("intentName", context); + * + * //resolve a "Client-Service" type intent with a data response + * let resolution = await agent.raiseIntent("intentName", context); + * try { + * const result = await resolution.getData(); + * 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}`); + * } * ``` */ export interface IntentResolution { + /** + * The application that resolved the intent. + */ readonly source: TargetApp; /** - * @deprecated not assignable from intent listeners + * 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 will + * reject if an error is thrown by the intent handler or the promise + * returned by the intent handler is reject. If the intent handler + * does not return a promise this function will return null. */ - readonly data?: object; - readonly version: string; + getData(): Promise | null; } diff --git a/src/api/Methods.ts b/src/api/Methods.ts index 631769eac..93163f30d 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; @@ -63,7 +72,7 @@ export function raiseIntentForContext(context: Context, app?: TargetApp): Promis return rejectIfNoGlobal(() => window.fdc3.raiseIntentForContext(context, app)); } -export function addIntentListener(intent: string, handler: ContextHandler): Listener { +export function addIntentListener(intent: string, handler: IntentHandler): Listener { return throwIfNoGlobal(() => window.fdc3.addIntentListener(intent, handler)); } diff --git a/src/api/Types.ts b/src/api/Types.ts index 4965f8e88..6a93d1b16 100644 --- a/src/api/Types.ts +++ b/src/api/Types.ts @@ -6,5 +6,21 @@ 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. + * Used when attaching listeners for raised intents. + */ +export type IntentHandler = (context: Context) => Promise | void; From 1da09e6bc4d3d04fe000332ab39df829c61f4e07 Mon Sep 17 00:00:00 2001 From: Kris West Date: Thu, 11 Nov 2021 13:24:08 +0000 Subject: [PATCH 02/11] Set PR number in changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea1d20c82..ecfe29fe6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +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 `getData()` to IntentResolution, both of which return a Promise of a Context object. ([#XXX](https://github.com/finos/FDC3/pull/XXX)) +* Added the ability to return data from an intent, via the addition of an IntentHandler type and a `getData()` to IntentResolution, both of which return a Promise of a Context object. ([#495](https://github.com/finos/FDC3/pull/495)) ### Changed * Consolidated `Listener` documentation with other types ([#404](https://github.com/finos/FDC3/pull/404)) From 86fa4951a5c70a17f217cb842b2abde4d9482bfb Mon Sep 17 00:00:00 2001 From: Kris West Date: Fri, 12 Nov 2021 11:34:34 +0000 Subject: [PATCH 03/11] Ensuring IntentResolution.getData always returns a promise and standardizing error strings that it can reject with --- docs/api/ref/DesktopAgent.md | 29 ++++++++++++++++++----------- docs/api/ref/Errors.md | 16 ++++++++++++++++ docs/api/ref/Metadata.md | 8 ++------ docs/api/spec.md | 14 +++++--------- src/api/DesktopAgent.ts | 26 +++++++++++--------------- src/api/Errors.ts | 5 +++++ src/api/IntentResolution.ts | 10 +++++----- 7 files changed, 62 insertions(+), 46 deletions(-) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 306950163..ca2bf6689 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -80,7 +80,7 @@ const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... ```ts addIntentListener(intent: string, handler: IntentHandler): Listener; ``` -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 is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. + 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 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 `getData()` function of the `IntentResolution`. #### Examples @@ -92,11 +92,11 @@ const listener = fdc3.addIntentListener('StartChat', context => { }); //Handle a raised intent and return Context data via a promise -fdc3.addIntentListener("trade", (context) => { - return new Promise((resolve) => { - // go place trade - resolve({result: "trade placed successfully"}); - }); +fdc3.addIntentListener("CreateOrder", (context) => { + return new Promise((resolve) => { + // go create the order + resolve({type: "fdc3.order", id: { "orderId": 1234}}); + }); }); ``` @@ -401,7 +401,7 @@ Alternatively, the specific app to target can also be provided. A list of valid 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 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. +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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, the promise returned is rejected, or a promse is not returned then the Desktop Agent MUST reject the promise returned by the `getData()` 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`](Errors#resolverrror) enumeration is returned. @@ -410,20 +410,27 @@ If a target app for the intent cannot be found with the criteria provided, an `E ```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 - target applied, if more than one application can resolve the intent +// target applied, 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 name of one of the associated apps returned by findIntent as the specific intent target await fdc3.raiseIntent("StartChat", context, appIntent.apps[0].name); - // or use the metadata of the app to fully 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.getData(); + console.log(`${resolution.source} returned ${JSON.stringify(result)}`); +} catch(error) { + console.error(`${resolution.source} returned a data error: ${error}`); +} ``` #### See also * [`Context`](Types#context) @@ -444,7 +451,7 @@ Alternatively, the specific app to target can also be provided, in which case an 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 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. +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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, the promise returned is rejected, or a promse is not returned then the Desktop Agent MUST reject the promise returned by the `getData()` 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`](Errors#resolveerror) enumeration is returned. diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index c2ca879d9..88470a3f9 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -36,6 +36,22 @@ Contains constants representing the errors that can be encountered when calling * [`DesktopAgent.findIntent`](DesktopAgent#findintent) * [`DesktopAgent.findIntentsByContext`](DesktopAgent#findintentsbycontext) +## `DataError` + +```typescript +enum DataError { + NoDataReturned = 'NoDataReturned', + IntentHandlerRejected = 'IntentHandlerRejected', +} +``` + +Contains constants representing the errors that can be encountered when calling the [`getData`](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 46ebc7fb1..1653fd4b7 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -155,12 +155,8 @@ let resolution = await agent.raiseIntent("intentName", context); //resolve a "Client-Service" type intent with a data response let resolution = await agent.raiseIntent("intentName", context); try { - const result = await resolution.getData(); - if (result) { - console.log(`${resolution.source} returned ${JSON.stringify(result)}`); - } else { - console.error(`${resolution.source} didn't return data` - } + const result = await resolution.getData(); + console.log(`${resolution.source} returned ${JSON.stringify(result)}`); } catch(error) { console.error(`${resolution.source} returned an error: ${error}`); } diff --git a/docs/api/spec.md b/docs/api/spec.md index d8e81b0f6..5d8b01d22 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -123,9 +123,9 @@ Raising an Intent will return a Promise-type object that will resolve/reject bas If the raising of the intent resolves (or rejects), a standard object will be passed into the resolver function with the following format: -```js -{ - /** +```ts +interface IntentResolution { +/** * The application that resolved the intent. */ readonly source: TargetApp; @@ -173,13 +173,9 @@ Raise an intent and retrieve data from the IntentResolution: let resolution = await agent.raiseIntent("intentName", context); try { const result = await resolution.getData(); - if (result) { - console.log(`${resolution.source} returned ${JSON.stringify(result)}`); - } else { - console.error(`${resolution.source} didn't return data` - } + console.log(`${resolution.source} returned ${JSON.stringify(result)}`); } catch(error) { - console.error(`${resolution.source} returned an error: ${error}`); + console.error(`${resolution.source} returned a data error: ${error}`); } ``` diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index fdde71084..5e650f356 100644 --- a/src/api/DesktopAgent.ts +++ b/src/api/DesktopAgent.ts @@ -125,9 +125,9 @@ export interface DesktopAgent { * 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 to target can also be provided. A list of valid target applications can be retrieved via `findIntent`. * - * 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. + * 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 `getData()` function of the IntentResolution object. If 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 `getData()` 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 @@ -148,13 +148,9 @@ export interface DesktopAgent { * let resolution = await agent.raiseIntent("intentName", context); * try { * const result = await resolution.getData(); - * if (result) { - * console.log(`${resolution.source} returned ${JSON.stringify(result)}`); - * } else { - * console.error(`${resolution.source} didn't return data` - * } + * console.log(`${resolution.source} returned ${JSON.stringify(result)}`); * } catch(error) { - * console.error(`${resolution.source} returned an error: ${error}`); + * console.error(`${resolution.source} returned a data error: ${error}`); * } * ``` */ @@ -168,7 +164,7 @@ export interface DesktopAgent { * * 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 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, or the promise returned is rejected, then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution`. + * 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 `getData()` function of the IntentResolution object. If 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 `getData()` 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. * @@ -185,9 +181,9 @@ export interface DesktopAgent { * 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 is - * thrown by the handler function, or the promise returned is rejected, then the - * Desktop Agent MUST reject the promise returned by the `getData()` function of - * the `IntentResolution`. + * 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 + * `getData()` function of the `IntentResolution`. * * ```javascript * //Handle a raised intent @@ -197,10 +193,10 @@ export interface DesktopAgent { * }); * * //Handle a raised intent and return Context data via a promise - * fdc3.addIntentListener("trade", (context) => { + * fdc3.addIntentListener("CreateOrder", (context) => { * return new Promise((resolve) => { - * // go place trade - * resolve({result: "trade placed successfully"}); + * // go create the order + * resolve({type: "fdc3.order", id: { "orderId": 1234}}); * }); * }); * ``` diff --git a/src/api/Errors.ts b/src/api/Errors.ts index d8daabe12..b1b41c7dd 100644 --- a/src/api/Errors.ts +++ b/src/api/Errors.ts @@ -16,6 +16,11 @@ export enum ResolveError { ResolverTimeout = 'ResolverTimeout', } +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 205818519..3ec1f28cf 100644 --- a/src/api/IntentResolution.ts +++ b/src/api/IntentResolution.ts @@ -37,10 +37,10 @@ export interface IntentResolution { readonly version?: string; /** * Retrieves a promise that will resolve to data returned by the - * application that resolves the raised intent. The promise will - * reject if an error is thrown by the intent handler or the promise - * returned by the intent handler is reject. If the intent handler - * does not return a promise this function will return null. + * 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. */ - getData(): Promise | null; + getData(): Promise; } From d83d40f58c6fad09b79c084f565f61ce1107fcb0 Mon Sep 17 00:00:00 2001 From: Kris West Date: Fri, 12 Nov 2021 11:35:50 +0000 Subject: [PATCH 04/11] prettier --- src/api/IntentResolution.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/IntentResolution.ts b/src/api/IntentResolution.ts index 3ec1f28cf..5144746c1 100644 --- a/src/api/IntentResolution.ts +++ b/src/api/IntentResolution.ts @@ -38,9 +38,9 @@ export interface IntentResolution { /** * 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. + * 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. */ getData(): Promise; } From 07c6c93f8e0c3ecc44e31a4b447912f6951dbb78 Mon Sep 17 00:00:00 2001 From: Kris West Date: Thu, 18 Nov 2021 14:40:22 +0000 Subject: [PATCH 05/11] Changing IntentResolution.getData() to IntentResolution.getResult() --- docs/api/ref/DesktopAgent.md | 8 ++++---- docs/api/ref/Errors.md | 2 +- docs/api/ref/Metadata.md | 4 ++-- docs/api/spec.md | 4 ++-- src/api/DesktopAgent.ts | 8 ++++---- src/api/IntentResolution.ts | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index ca2bf6689..f02dd76a0 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -80,7 +80,7 @@ const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... ```ts addIntentListener(intent: string, handler: IntentHandler): Listener; ``` - 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 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 `getData()` function of the `IntentResolution`. + 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 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 @@ -401,7 +401,7 @@ Alternatively, the specific app to target can also be provided. A list of valid 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 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, the promise returned is rejected, or a promse is not returned then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution` with a string from the `DataError` enumeration. +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 is thrown by the handler function, the promise returned is rejected, or a promse is not 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`](Errors#resolverrror) enumeration is returned. @@ -426,7 +426,7 @@ 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.getData(); + const result = await resolution.getResult(); console.log(`${resolution.source} returned ${JSON.stringify(result)}`); } catch(error) { console.error(`${resolution.source} returned a data error: ${error}`); @@ -451,7 +451,7 @@ Alternatively, the specific app to target can also be provided, in which case an 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 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 `getData()` function of the IntentResolution object. If an error is thrown by the handler function, the promise returned is rejected, or a promse is not returned then the Desktop Agent MUST reject the promise returned by the `getData()` function of the `IntentResolution` with a string from the `DataError` enumeration. +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 is thrown by the handler function, the promise returned is rejected, or a promse is not 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`](Errors#resolveerror) enumeration is returned. diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index 88470a3f9..761dd46b1 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -45,7 +45,7 @@ enum DataError { } ``` -Contains constants representing the errors that can be encountered when calling the [`getData`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object. +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) diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index 1653fd4b7..c57454964 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -141,7 +141,7 @@ interface IntentResolution { * returned by the intent handler is reject. If the intent handler * does not return a promise this function will return null. */ - getData(): Promise | null; + getResult(): Promise | null; } ``` @@ -155,7 +155,7 @@ let resolution = await agent.raiseIntent("intentName", context); //resolve a "Client-Service" type intent with a data response let resolution = await agent.raiseIntent("intentName", context); try { - const result = await resolution.getData(); + const result = await resolution.getResult(); console.log(`${resolution.source} returned ${JSON.stringify(result)}`); } catch(error) { console.error(`${resolution.source} returned an error: ${error}`); diff --git a/docs/api/spec.md b/docs/api/spec.md index 5d8b01d22..71f3b81b7 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -140,7 +140,7 @@ interface IntentResolution { * returned by the intent handler is reject. If the intent handler * does not return a promise this function will return null. */ - getData(): Promise | null; + getResult(): Promise | null; } ``` @@ -172,7 +172,7 @@ Raise an intent and retrieve data from the IntentResolution: ```js let resolution = await agent.raiseIntent("intentName", context); try { - const result = await resolution.getData(); + const result = await resolution.getResult(); console.log(`${resolution.source} returned ${JSON.stringify(result)}`); } catch(error) { console.error(`${resolution.source} returned a data error: ${error}`); diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index 5e650f356..b73099912 100644 --- a/src/api/DesktopAgent.ts +++ b/src/api/DesktopAgent.ts @@ -125,7 +125,7 @@ export interface DesktopAgent { * 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 to target can also be provided. A list of valid target applications can be retrieved via `findIntent`. * - * 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 `getData()` function of the IntentResolution object. If 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 `getData()` function of the `IntentResolution` with a string from the `DataError` enumeration. + * 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 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 MUST be returned. * @@ -147,7 +147,7 @@ export interface DesktopAgent { * //Raise an intent and retrieve data from the IntentResolution * let resolution = await agent.raiseIntent("intentName", context); * try { - * const result = await resolution.getData(); + * const result = await resolution.getResult(); * console.log(`${resolution.source} returned ${JSON.stringify(result)}`); * } catch(error) { * console.error(`${resolution.source} returned a data error: ${error}`); @@ -164,7 +164,7 @@ export interface DesktopAgent { * * 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 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 `getData()` function of the IntentResolution object. If 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 `getData()` function of the `IntentResolution` with a string from the `DataError` enumeration. + * 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 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. * @@ -183,7 +183,7 @@ export interface DesktopAgent { * any data that should be returned to 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 - * `getData()` function of the `IntentResolution`. + * `getResult()` function of the `IntentResolution`. * * ```javascript * //Handle a raised intent diff --git a/src/api/IntentResolution.ts b/src/api/IntentResolution.ts index 5144746c1..e73ddc148 100644 --- a/src/api/IntentResolution.ts +++ b/src/api/IntentResolution.ts @@ -15,7 +15,7 @@ import { TargetApp } from './Types'; * //resolve a "Client-Service" type intent with a data response * let resolution = await agent.raiseIntent("intentName", context); * try { - * const result = await resolution.getData(); + * const result = await resolution.getResult(); * if (result) { * console.log(`${resolution.source} returned ${JSON.stringify(result)}`); * } else { @@ -42,5 +42,5 @@ export interface IntentResolution { * is thrown by the intent handler, it rejects the returned promise, * or it does not return a promise. */ - getData(): Promise; + getResult(): Promise; } From 9aac821ea543aed30c8d0a03a6cf64464e1c4912 Mon Sep 17 00:00:00 2001 From: Kris West Date: Thu, 18 Nov 2021 14:42:34 +0000 Subject: [PATCH 06/11] Changing IntentResolution.getData() to IntentResolution.getResult() --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecfe29fe6..6f35e5c36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +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 `getData()` to IntentResolution, both of which return a Promise of a Context object. ([#495](https://github.com/finos/FDC3/pull/495)) +* 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)) ### Changed * Consolidated `Listener` documentation with other types ([#404](https://github.com/finos/FDC3/pull/404)) From c2c026de3d66cf915fd445112fefd9a5e907a422 Mon Sep 17 00:00:00 2001 From: Kris West Date: Mon, 13 Dec 2021 14:44:52 +0000 Subject: [PATCH 07/11] Apply suggestions from code review --- docs/api/ref/Metadata.md | 9 +++++---- docs/api/spec.md | 10 +++++----- src/api/Types.ts | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index c57454964..c9ffc1718 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -136,10 +136,11 @@ interface IntentResolution { readonly version?: string; /** * Retrieves a promise that will resolve to data returned by the - * application that resolves the raised intent. The promise will - * reject if an error is thrown by the intent handler or the promise - * returned by the intent handler is reject. If the intent handler - * does not return a promise this function will return null. + * application that resolves the raised intent. If 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 | null; } diff --git a/docs/api/spec.md b/docs/api/spec.md index 71f3b81b7..2efa0cad5 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -135,12 +135,12 @@ interface IntentResolution { readonly version?: string; /** * Retrieves a promise that will resolve to data returned by the - * application that resolves the raised intent. The promise will - * reject if an error is thrown by the intent handler or the promise - * returned by the intent handler is reject. If the intent handler - * does not return a promise this function will return null. + * application that resolves the raised intent. If 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 | null; + getResult(): Promise; } ``` diff --git a/src/api/Types.ts b/src/api/Types.ts index 6a93d1b16..4bb39c5e3 100644 --- a/src/api/Types.ts +++ b/src/api/Types.ts @@ -20,7 +20,7 @@ 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. + * 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; From 78d2718b91253b7daf817c5af7a8a1fc000a1a5a Mon Sep 17 00:00:00 2001 From: Kris West Date: Mon, 13 Dec 2021 14:45:36 +0000 Subject: [PATCH 08/11] Apply suggestions from code review --- docs/api/ref/Metadata.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index c9ffc1718..d48757840 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -142,7 +142,7 @@ interface IntentResolution { * the promise returned by the `getResult()` function of the * `IntentResolution` with a string from the `DataError` enumeration. */ - getResult(): Promise | null; + getResult(): Promise; } ``` From b6c4f8ac17696a94b1efc70bb18d3c678a98a211 Mon Sep 17 00:00:00 2001 From: Kris West Date: Tue, 21 Dec 2021 10:49:22 +0000 Subject: [PATCH 09/11] Apply suggestions from code review Co-authored-by: Matt Jamieson <10372+mattjamieson@users.noreply.github.com> --- docs/api/ref/DesktopAgent.md | 2 +- src/api/Types.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index f02dd76a0..ac3112c92 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -95,7 +95,7 @@ const listener = fdc3.addIntentListener('StartChat', context => { fdc3.addIntentListener("CreateOrder", (context) => { return new Promise((resolve) => { // go create the order - resolve({type: "fdc3.order", id: { "orderId": 1234}}); + resolve({type: "fdc3.order", id: { "orderId": 1234 }}); }); }); ``` diff --git a/src/api/Types.ts b/src/api/Types.ts index 4bb39c5e3..d1ab34bdf 100644 --- a/src/api/Types.ts +++ b/src/api/Types.ts @@ -20,7 +20,10 @@ 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). + * 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; From 92c2157c47f2e931a947708071a20ba4e49610f1 Mon Sep 17 00:00:00 2001 From: Kris West Date: Fri, 4 Feb 2022 20:01:39 +0000 Subject: [PATCH 10/11] Apply suggestions from code review Co-authored-by: Hugh Troeger --- docs/api/ref/DesktopAgent.md | 6 +++--- docs/api/ref/Metadata.md | 11 ++++++----- docs/api/spec.md | 12 ++++++------ src/api/DesktopAgent.ts | 12 ++++++------ 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 6a91a952a..e04552a2b 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -84,7 +84,7 @@ const contactListener = await fdc3.addContextListener('fdc3.contact', contact => ```ts addIntentListener(intent: string, handler: IntentHandler): Promise; ``` - 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 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`. + 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 @@ -455,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 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 is thrown by the handler function, the promise returned is rejected, or a promse is not returned then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution` with a string from the `DataError` enumeration. +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. @@ -504,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 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 is thrown by the handler function, the promise returned is rejected, or a promse is not returned then the Desktop Agent MUST reject the promise returned by the `getResult()` function of the `IntentResolution` with a string from the `DataError` enumeration. +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/Metadata.md b/docs/api/ref/Metadata.md index ecbc0bb06..43bf40dd9 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -167,11 +167,12 @@ interface IntentResolution { readonly version?: string; /** * Retrieves a promise that will resolve to data returned by the - * application that resolves the raised intent. If 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. + * 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; } diff --git a/docs/api/spec.md b/docs/api/spec.md index f6fea1a51..068142a14 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -99,7 +99,7 @@ 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 as input. 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. @@ -141,11 +141,11 @@ interface IntentResolution { */ readonly version?: string; /** - * Retrieves a promise that will resolve to data returned by the - * application that resolves the raised intent. If 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. + * 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; } diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index 106462d2e..ebf8ae8f2 100644 --- a/src/api/DesktopAgent.ts +++ b/src/api/DesktopAgent.ts @@ -175,7 +175,7 @@ export interface DesktopAgent { * * 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. 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 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. + * 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 MUST be returned. * @@ -213,7 +213,7 @@ export interface DesktopAgent { * * 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 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 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. + * 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. * @@ -229,10 +229,10 @@ export interface DesktopAgent { /** * 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 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`. + * 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 From e3ccac0f5635cdee528130761572ec49398d96d6 Mon Sep 17 00:00:00 2001 From: Kris West Date: Fri, 4 Feb 2022 20:05:12 +0000 Subject: [PATCH 11/11] prettier --- src/api/DesktopAgent.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index ebf8ae8f2..cc3fe9b74 100644 --- a/src/api/DesktopAgent.ts +++ b/src/api/DesktopAgent.ts @@ -229,9 +229,9 @@ export interface DesktopAgent { /** * 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 + * 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