Skip to content

Commit 0ece665

Browse files
authored
Merge pull request #516 from ChartIQ/362-DesktopAgent-and-Channel-APIs-should-be-async
362 All DesktopAgent and Channel APIs are async
2 parents c1b0acb + 48071af commit 0ece665

9 files changed

+78
-69
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1919
* Updated copyright notices ([#467](https://github.com/finos/FDC3/pull/467))
2020
* Adjusted wording in API spec and documentation to acknowledge the possibility of methods of intent resolution other than a resolver UI ([#461](https://github.com/finos/FDC3/pull/461))
2121
* Moved the Icon type definition into the Types documentation page for consistency with other types. ([#493](https://github.com/finos/FDC3/pull/493)
22+
* All DesktopAgent and Channel API functions are now async for consistency, changing the return type of the `broadcast`, `addIntentListener`, `addContextListener` and `getInfo` functions ([#516](https://github.com/finos/FDC3/pull/516))
2223

2324
### Deprecated
2425
### Fixed

docs/api/overview.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import { fdc3Ready, addIntentListener } from '@finos/fdc3'
6666

6767
await fdc3Ready();
6868

69-
const listener = addIntentListener('ViewAnalysis', instrument => {
69+
const listener = await addIntentListener('ViewAnalysis', instrument => {
7070
// handle intent
7171
})
7272
```

docs/api/ref/Channel.md

+9-9
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ interface Channel {
2020
displayMetadata?: DisplayMetadata;
2121

2222
// methods
23-
broadcast(context: Context): void;
23+
broadcast(context: Context): Promise<void>;
2424
getCurrentContext(contextType?: string): Promise<Context|null>;
25-
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
25+
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
2626
/**
2727
* @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
2828
*/
29-
addContextListener(handler: ContextHandler): Listener;
29+
addContextListener(handler: ContextHandler): Promise<Listener>;
3030
}
3131
```
3232

@@ -72,15 +72,15 @@ DisplayMetadata can be used to provide display hints for channels intended to be
7272

7373
### `addContextListener`
7474
```ts
75-
public addContextListener(contextType: string | null, handler: ContextHandler): Listener;
75+
public addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
7676
```
7777
Adds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel.
7878

7979
```ts
8080
/**
8181
* @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
8282
*/
83-
public addContextListener(handler: ContextHandler): Listener;
83+
public addContextListener(handler: ContextHandler): Promise<Listener>;
8484
```
8585
Adds a listener for incoming contexts whenever a broadcast happens on the channel.
8686

@@ -90,7 +90,7 @@ Adds a listener for incoming contexts whenever a broadcast happens on the channe
9090
Add a listener for any context that is broadcast on the channel:
9191

9292
```ts
93-
const listener = channel.addContextListener(null, context => {
93+
const listener = await channel.addContextListener(null, context => {
9494
if (context.type === 'fdc3.contact') {
9595
// handle the contact
9696
} else if (context.type === 'fdc3.instrument') => {
@@ -105,11 +105,11 @@ listener.unsubscribe();
105105
Adding listeners for specific types of context that is broadcast on the channel:
106106

107107
```ts
108-
const contactListener = channel.addContextListener('fdc3.contact', contact => {
108+
const contactListener = await channel.addContextListener('fdc3.contact', contact => {
109109
// handle the contact
110110
});
111111

112-
const instrumentListener = channel.addContextListener('fdc3.instrument', instrument => {
112+
const instrumentListener = await channel.addContextListener('fdc3.instrument', instrument => {
113113
// handle the instrument
114114
});
115115

@@ -127,7 +127,7 @@ instrumentListener.unsubscribe();
127127
### `broadcast`
128128

129129
```typescript
130-
public broadcast(context: Context): void;
130+
public broadcast(context: Context): Promise<void>;
131131
```
132132

133133
Broadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on channels that they aren't a member of.

docs/api/ref/DesktopAgent.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ interface DesktopAgent {
1818
open(app: TargetApp, context?: Context): Promise<void>;
1919

2020
// context
21-
broadcast(context: Context): void;
22-
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
21+
broadcast(context: Context): Promise<void>;
22+
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
2323
/**
2424
* @deprecated 'Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
2525
*/
26-
addContextListener(handler: ContextHandler): Listener;
26+
addContextListener(handler: ContextHandler): Promise<Listener>;
2727

2828
// intents
2929
findIntent(intent: string, context?: Context): Promise<AppIntent>;
3030
findIntentsByContext(context: Context): Promise<Array<AppIntent>>;
3131
raiseIntent(intent: string, context: Context, app?: TargetApp): Promise<IntentResolution>;
3232
raiseIntentForContext(context: Context, app?: TargetApp): Promise<IntentResolution>;
33-
addIntentListener(intent: string, handler: ContextHandler): Listener;
33+
addIntentListener(intent: string, handler: ContextHandler): Promise<Listener>;
3434

3535
// channels
3636
getOrCreateChannel(channelId: string): Promise<Channel>;
@@ -40,7 +40,7 @@ interface DesktopAgent {
4040
leaveCurrentChannel() : Promise<void>;
4141

4242
//implementation info
43-
getInfo(): ImplementationMetadata;
43+
getInfo(): Promise<ImplementationMetadata>;
4444
}
4545
```
4646

@@ -49,11 +49,11 @@ interface DesktopAgent {
4949
### `addContextListener`
5050

5151
```ts
52-
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
52+
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
5353
/**
5454
* @deprecated 'Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
5555
*/
56-
addContextListener(handler: ContextHandler): Listener;
56+
addContextListener(handler: ContextHandler): Promise<Listener>;
5757
```
5858
Adds a listener for incoming context broadcasts from the Desktop Agent. If the consumer is only interested in a context of a particular type, they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.
5959

@@ -62,10 +62,10 @@ Context broadcasts are only received from apps that are joined to the same chann
6262
#### Examples
6363
```js
6464
// any context
65-
const listener = fdc3.addContextListener(null, context => { ... });
65+
const listener = await fdc3.addContextListener(null, context => { ... });
6666

6767
// listener for a specific type
68-
const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... });
68+
const contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });
6969
```
7070

7171
#### See also
@@ -77,14 +77,14 @@ const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ...
7777
### `addIntentListener`
7878

7979
```ts
80-
addIntentListener(intent: string, handler: ContextHandler): Listener;
80+
addIntentListener(intent: string, handler: ContextHandler): Promise<Listener>;
8181
```
8282
Adds a listener for incoming Intents from the Agent.
8383

8484
#### Examples
8585

8686
```js
87-
const listener = fdc3.addIntentListener('StartChat', context => {
87+
const listener = await fdc3.addIntentListener('StartChat', context => {
8888
// start chat has been requested by another application
8989
});
9090
```
@@ -98,7 +98,7 @@ const listener = fdc3.addIntentListener('StartChat', context => {
9898
### `broadcast`
9999

100100
```ts
101-
broadcast(context: Context): void;
101+
broadcast(context: Context): Promise<void>;
102102
```
103103

104104
Publishes context to other apps on the desktop. Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever `Channel` the app is joined to. If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect. Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.
@@ -219,7 +219,7 @@ let current = await fdc3.getCurrentChannel();
219219
### `getInfo`
220220

221221
```ts
222-
getInfo(): ImplementationMetadata;
222+
getInfo(): Promise<ImplementationMetadata>;
223223
```
224224

225225
Retrieves information about the FDC3 Desktop Agent implementation, such as the implemented version of the FDC3 specification and the name of the implementation provider.
@@ -231,7 +231,7 @@ Returns an [`ImplementationMetadata`](Metadata#implementationmetadata) object.
231231
```js
232232
import {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';
233233

234-
if (fdc3.getInfo && versionIsAtLeast(fdc3.getInfo(), "1.2")) {
234+
if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), "1.2")) {
235235
await fdc3.raiseIntentForContext(context);
236236
} else {
237237
await fdc3.raiseIntent("ViewChart", context);

docs/api/spec.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ From version 1.2 of the FDC3 specification, Desktop Agent implementations MUST p
205205
```js
206206
import {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';
207207

208-
if (fdc3.getInfo && versionIsAtLeast(fdc3.getInfo(), '1.2')) {
208+
if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) {
209209
await fdc3.raiseIntentForContext(context);
210210
} else {
211211
await fdc3.raiseIntent('ViewChart', context);
@@ -321,9 +321,9 @@ const appChannel = await fdc3.getOrCreateChannel('my_custom_channel');
321321
// get the current context of the channel
322322
const current = await appChannel.getCurrentContext();
323323
// add a listener
324-
appChannel.addContextListener(null, context => {...});
324+
await appChannel.addContextListener(null, context => {...});
325325
// broadcast to the channel
326-
appChannel.broadcast(context);
326+
await appChannel.broadcast(context);
327327

328328
```
329329

src/api/Channel.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export interface Channel {
4040
*
4141
* `Error` with a string from the `ChannelError` enumeration.
4242
*/
43-
broadcast(context: Context): void;
43+
broadcast(context: Context): Promise<void>;
4444

4545
/**
4646
* Returns the last context that was broadcast on this channel. All channels initially have no context, until a
@@ -63,10 +63,10 @@ export interface Channel {
6363
* Adds a listener for incoming contexts whenever a broadcast happens on this channel.
6464
* @deprecated use `addContextListener(null, handler)` instead of `addContextListener(handler)`.
6565
*/
66-
addContextListener(handler: ContextHandler): Listener;
66+
addContextListener(handler: ContextHandler): Promise<Listener>;
6767

6868
/**
6969
* Adds a listener for incoming contexts of the specified context type whenever a broadcast happens on this channel.
7070
*/
71-
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
71+
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
7272
}

src/api/DesktopAgent.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export interface DesktopAgent {
117117
* fdc3.broadcast(context);
118118
* ```
119119
*/
120-
broadcast(context: Context): void;
120+
broadcast(context: Context): Promise<void>;
121121

122122
/**
123123
* Raises a specific intent for resolution against apps registered with the desktop agent.
@@ -169,13 +169,13 @@ export interface DesktopAgent {
169169
/**
170170
* Adds a listener for incoming Intents from the Agent.
171171
*/
172-
addIntentListener(intent: string, handler: ContextHandler): Listener;
172+
addIntentListener(intent: string, handler: ContextHandler): Promise<Listener>;
173173

174174
/**
175175
* Adds a listener for incoming context broadcast from the Desktop Agent.
176176
* @deprecated use `addContextListener(null, handler)` instead of `addContextListener(handler)`.
177177
*/
178-
addContextListener(handler: ContextHandler): Listener;
178+
addContextListener(handler: ContextHandler): Promise<Listener>;
179179

180180
/**
181181
* Adds a listener for incoming context broadcasts from the Desktop Agent. If the consumer is only interested in a context of a particular type, they can they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.
@@ -187,7 +187,7 @@ export interface DesktopAgent {
187187
* const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... });
188188
* ```
189189
*/
190-
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
190+
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
191191

192192
/**
193193
* Retrieves a list of the System channels available for the app to join
@@ -243,5 +243,5 @@ export interface DesktopAgent {
243243
* the implemented version of the FDC3 specification and the name of the implementation
244244
* provider.
245245
*/
246-
getInfo(): ImplementationMetadata;
246+
getInfo(): Promise<ImplementationMetadata>;
247247
}

src/api/Methods.ts

+24-16
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,21 @@ function rejectIfNoGlobal(f: () => Promise<any>) {
1111
return window.fdc3 ? f() : Promise.reject(UnavailableError);
1212
}
1313

14-
function throwIfNoGlobal(f: () => any) {
15-
if (!window.fdc3) {
16-
throw UnavailableError;
17-
}
18-
return f();
19-
}
20-
14+
/**
15+
* Utility function that returns a promise that will resolve immeadiately
16+
* if the desktop agent API is found at `window.fdc3`. If the API is found,
17+
* the promise will resolve when the `fdc3Ready` event is received or if it
18+
* is found at the end of the specified timeout. If the API is not found, it
19+
* will reject with an error.
20+
*
21+
* ```javascript
22+
* await fdc3Ready();
23+
* const intentListener = await addIntentListener("ViewChart", intentHandlerFn);
24+
* ```
25+
*
26+
* @param waitForMs The number of milliseconds to wait for the FDC3 API to be
27+
* ready. Defaults to 5 seconds.
28+
*/
2129
export const fdc3Ready = async (waitForMs = DEFAULT_TIMEOUT): Promise<void> => {
2230
return new Promise((resolve, reject) => {
2331
// if the global is already available resolve immediately
@@ -51,8 +59,8 @@ export function findIntentsByContext(context: Context): Promise<AppIntent[]> {
5159
return rejectIfNoGlobal(() => window.fdc3.findIntentsByContext(context));
5260
}
5361

54-
export function broadcast(context: Context): void {
55-
throwIfNoGlobal(() => window.fdc3.broadcast(context));
62+
export function broadcast(context: Context): Promise<void> {
63+
return rejectIfNoGlobal(() => window.fdc3.broadcast(context));
5664
}
5765

5866
export function raiseIntent(intent: string, context: Context, app?: TargetApp): Promise<IntentResolution> {
@@ -63,19 +71,19 @@ export function raiseIntentForContext(context: Context, app?: TargetApp): Promis
6371
return rejectIfNoGlobal(() => window.fdc3.raiseIntentForContext(context, app));
6472
}
6573

66-
export function addIntentListener(intent: string, handler: ContextHandler): Listener {
67-
return throwIfNoGlobal(() => window.fdc3.addIntentListener(intent, handler));
74+
export function addIntentListener(intent: string, handler: ContextHandler): Promise<Listener> {
75+
return rejectIfNoGlobal(() => window.fdc3.addIntentListener(intent, handler));
6876
}
6977

7078
export function addContextListener(
7179
contextTypeOrHandler: string | null | ContextHandler,
7280
handler?: ContextHandler
73-
): Listener {
81+
): Promise<Listener> {
7482
//Handle (deprecated) function signature that allowed contextType argument to be omitted
7583
if (typeof contextTypeOrHandler !== 'function') {
76-
return throwIfNoGlobal(() => window.fdc3.addContextListener(contextTypeOrHandler, handler as ContextHandler));
84+
return rejectIfNoGlobal(() => window.fdc3.addContextListener(contextTypeOrHandler, handler as ContextHandler));
7785
} else {
78-
return throwIfNoGlobal(() => window.fdc3.addContextListener(null, contextTypeOrHandler as ContextHandler));
86+
return rejectIfNoGlobal(() => window.fdc3.addContextListener(null, contextTypeOrHandler as ContextHandler));
7987
}
8088
}
8189

@@ -99,8 +107,8 @@ export function leaveCurrentChannel(): Promise<void> {
99107
return rejectIfNoGlobal(() => window.fdc3.leaveCurrentChannel());
100108
}
101109

102-
export function getInfo(): ImplementationMetadata {
103-
return throwIfNoGlobal(() => window.fdc3.getInfo());
110+
export function getInfo(): Promise<ImplementationMetadata> {
111+
return rejectIfNoGlobal(() => window.fdc3.getInfo());
104112
}
105113

106114
/**

0 commit comments

Comments
 (0)