Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

362 All DesktopAgent and Channel APIs are async #516

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Updated copyright notices ([#467](https://github.com/finos/FDC3/pull/467))
* 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))
* Moved the Icon type definition into the Types documentation page for consistency with other types. ([#493](https://github.com/finos/FDC3/pull/493)
* 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))

### Deprecated
### Fixed
Expand Down
2 changes: 1 addition & 1 deletion docs/api/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import { fdc3Ready, addIntentListener } from '@finos/fdc3'

await fdc3Ready();

const listener = addIntentListener('ViewAnalysis', instrument => {
const listener = await addIntentListener('ViewAnalysis', instrument => {
// handle intent
})
```
Expand Down
18 changes: 9 additions & 9 deletions docs/api/ref/Channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ interface Channel {
displayMetadata?: DisplayMetadata;

// methods
broadcast(context: Context): void;
broadcast(context: Context): Promise<void>;
getCurrentContext(contextType?: string): Promise<Context|null>;
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
/**
* @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
*/
addContextListener(handler: ContextHandler): Listener;
addContextListener(handler: ContextHandler): Promise<Listener>;
}
```

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

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

```ts
/**
* @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
*/
public addContextListener(handler: ContextHandler): Listener;
public addContextListener(handler: ContextHandler): Promise<Listener>;
```
Adds a listener for incoming contexts whenever a broadcast happens on the channel.

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

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

```ts
const contactListener = channel.addContextListener('fdc3.contact', contact => {
const contactListener = await channel.addContextListener('fdc3.contact', contact => {
// handle the contact
});

const instrumentListener = channel.addContextListener('fdc3.instrument', instrument => {
const instrumentListener = await channel.addContextListener('fdc3.instrument', instrument => {
// handle the instrument
});

Expand All @@ -127,7 +127,7 @@ instrumentListener.unsubscribe();
### `broadcast`

```typescript
public broadcast(context: Context): void;
public broadcast(context: Context): Promise<void>;
```

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.
Expand Down
28 changes: 14 additions & 14 deletions docs/api/ref/DesktopAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ interface DesktopAgent {
open(app: TargetApp, context?: Context): Promise<void>;

// context
broadcast(context: Context): void;
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
broadcast(context: Context): Promise<void>;
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
/**
* @deprecated 'Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
*/
addContextListener(handler: ContextHandler): Listener;
addContextListener(handler: ContextHandler): Promise<Listener>;

// intents
findIntent(intent: string, context?: Context): Promise<AppIntent>;
findIntentsByContext(context: Context): Promise<Array<AppIntent>>;
raiseIntent(intent: string, context: Context, app?: TargetApp): Promise<IntentResolution>;
raiseIntentForContext(context: Context, app?: TargetApp): Promise<IntentResolution>;
addIntentListener(intent: string, handler: ContextHandler): Listener;
addIntentListener(intent: string, handler: ContextHandler): Promise<Listener>;

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

//implementation info
getInfo(): ImplementationMetadata;
getInfo(): Promise<ImplementationMetadata>;
}
```

Expand All @@ -49,11 +49,11 @@ interface DesktopAgent {
### `addContextListener`

```ts
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
/**
* @deprecated 'Use `addContextListener(null, handler)` instead of `addContextListener(handler)`
*/
addContextListener(handler: ContextHandler): Listener;
addContextListener(handler: ContextHandler): Promise<Listener>;
```
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.

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

// listener for a specific type
const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... });
const contactListener = await fdc3.addContextListener('fdc3.contact', contact => { ... });
```

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

```ts
addIntentListener(intent: string, handler: ContextHandler): Listener;
addIntentListener(intent: string, handler: ContextHandler): Promise<Listener>;
```
Adds a listener for incoming Intents from the Agent.

#### Examples

```js
const listener = fdc3.addIntentListener('StartChat', context => {
const listener = await fdc3.addIntentListener('StartChat', context => {
// start chat has been requested by another application
});
```
Expand All @@ -98,7 +98,7 @@ const listener = fdc3.addIntentListener('StartChat', context => {
### `broadcast`

```ts
broadcast(context: Context): void;
broadcast(context: Context): Promise<void>;
```

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.
Expand Down Expand Up @@ -219,7 +219,7 @@ let current = await fdc3.getCurrentChannel();
### `getInfo`

```ts
getInfo(): ImplementationMetadata;
getInfo(): Promise<ImplementationMetadata>;
```

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

if (fdc3.getInfo && versionIsAtLeast(fdc3.getInfo(), "1.2")) {
if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), "1.2")) {
await fdc3.raiseIntentForContext(context);
} else {
await fdc3.raiseIntent("ViewChart", context);
Expand Down
6 changes: 3 additions & 3 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ From version 1.2 of the FDC3 specification, it is possible to retrieve informati
```js
import {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3';

if (fdc3.getInfo && versionIsAtLeast(fdc3.getInfo(), '1.2')) {
if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) {
await fdc3.raiseIntentForContext(context);
} else {
await fdc3.raiseIntent('ViewChart', context);
Expand Down Expand Up @@ -321,9 +321,9 @@ const appChannel = await fdc3.getOrCreateChannel('my_custom_channel');
// get the current context of the channel
const current = await appChannel.getCurrentContext();
// add a listener
appChannel.addContextListener(null, context => {...});
await appChannel.addContextListener(null, context => {...});
// broadcast to the channel
appChannel.broadcast(context);
await appChannel.broadcast(context);

```

Expand Down
6 changes: 3 additions & 3 deletions src/api/Channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface Channel {
*
* `Error` with a string from the `ChannelError` enumeration.
*/
broadcast(context: Context): void;
broadcast(context: Context): Promise<void>;

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

/**
* Adds a listener for incoming contexts of the specified context type whenever a broadcast happens on this channel.
*/
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;
}
10 changes: 5 additions & 5 deletions src/api/DesktopAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export interface DesktopAgent {
* fdc3.broadcast(context);
* ```
*/
broadcast(context: Context): void;
broadcast(context: Context): Promise<void>;

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

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

/**
* 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.
Expand All @@ -187,7 +187,7 @@ export interface DesktopAgent {
* const contactListener = fdc3.addContextListener('fdc3.contact', contact => { ... });
* ```
*/
addContextListener(contextType: string | null, handler: ContextHandler): Listener;
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;

/**
* Retrieves a list of the System channels available for the app to join
Expand Down Expand Up @@ -243,5 +243,5 @@ export interface DesktopAgent {
* the implemented version of the FDC3 specification and the name of the implementation
* provider.
*/
getInfo(): ImplementationMetadata;
getInfo(): Promise<ImplementationMetadata>;
}
40 changes: 24 additions & 16 deletions src/api/Methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ function rejectIfNoGlobal(f: () => Promise<any>) {
return window.fdc3 ? f() : Promise.reject(UnavailableError);
}

function throwIfNoGlobal(f: () => any) {
if (!window.fdc3) {
throw UnavailableError;
}
return f();
}

/**
* Utility function that returns a promise that will resolve immeadiately
* if the desktop agent API is found at `window.fdc3`. If the API is found,
* the promise will resolve when the `fdc3Ready` event is received or if it
* is found at the end of the specified timeout. If the API is not found, it
* will reject with an error.
*
* ```javascript
* await fdc3Ready();
* const intentListener = await addIntentListener("ViewChart", intentHandlerFn);
* ```
*
* @param waitForMs The number of milliseconds to wait for the FDC3 API to be
* ready. Defaults to 5 seconds.
*/
export const fdc3Ready = async (waitForMs = DEFAULT_TIMEOUT): Promise<void> => {
return new Promise((resolve, reject) => {
// if the global is already available resolve immediately
Expand Down Expand Up @@ -51,8 +59,8 @@ export function findIntentsByContext(context: Context): Promise<AppIntent[]> {
return rejectIfNoGlobal(() => window.fdc3.findIntentsByContext(context));
}

export function broadcast(context: Context): void {
throwIfNoGlobal(() => window.fdc3.broadcast(context));
export function broadcast(context: Context): Promise<void> {
return rejectIfNoGlobal(() => window.fdc3.broadcast(context));
}

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

export function addIntentListener(intent: string, handler: ContextHandler): Listener {
return throwIfNoGlobal(() => window.fdc3.addIntentListener(intent, handler));
export function addIntentListener(intent: string, handler: ContextHandler): Promise<Listener> {
return rejectIfNoGlobal(() => window.fdc3.addIntentListener(intent, handler));
}

export function addContextListener(
contextTypeOrHandler: string | null | ContextHandler,
handler?: ContextHandler
): Listener {
): Promise<Listener> {
//Handle (deprecated) function signature that allowed contextType argument to be omitted
if (typeof contextTypeOrHandler !== 'function') {
return throwIfNoGlobal(() => window.fdc3.addContextListener(contextTypeOrHandler, handler as ContextHandler));
return rejectIfNoGlobal(() => window.fdc3.addContextListener(contextTypeOrHandler, handler as ContextHandler));
} else {
return throwIfNoGlobal(() => window.fdc3.addContextListener(null, contextTypeOrHandler as ContextHandler));
return rejectIfNoGlobal(() => window.fdc3.addContextListener(null, contextTypeOrHandler as ContextHandler));
}
}

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

export function getInfo(): ImplementationMetadata {
return throwIfNoGlobal(() => window.fdc3.getInfo());
export function getInfo(): Promise<ImplementationMetadata> {
return rejectIfNoGlobal(() => window.fdc3.getInfo());
}

/**
Expand Down
Loading