diff --git a/CHANGELOG.md b/CHANGELOG.md index e8b957c15..a59b9a6ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Added clarification that `id` field values SHOULD always be strings to context schema definition (a restriction that can't easily be represented in the generated types). ([#1149](https://github.com/finos/FDC3/pull/1149)) * Added requirement that Standard versions SHOULD avoid the use unions in context and API definitions wherever possible as these can be hard to replicate and MUST avoid unions of primitive types as these can be impossible to replicate in other languages. ([#120](https://github.com/finos/FDC3/pull/1200)) -* Added reference materials and supported platforms information for FDC3 in .NET via the [finos/fdc3-dotnet](https://github.com/finos/fdc3-dotnet) project. ([#1108](https://github.com/finos/FDC3/pull/1108)) +* Added `addEventListener` to the `DesktopAgent` API to provide support for event listener for non-context and non-intent events, including a `userChannelChanged` event ([#1207](https://github.com/finos/FDC3/pull/1207)) +* Added an `async` `addEventListener` function to the `PrivateChannel` API to replace the deprecated, synchronous `onAddContextListener`, `onUnsubscribe` and `onDisconnect` functions and to keep consistency with the DesktopAgent API. ([#1305](https://github.com/finos/FDC3/pull/1305)) ### Changed +* `Listener.unsubscribe()` was made async (the return type was changed from `void` to `Promise`) for consistency with the rest of the API. ([#1305](https://github.com/finos/FDC3/pull/1305)) +* Added reference materials and supported platforms information for FDC3 in .NET via the [finos/fdc3-dotnet](https://github.com/finos/fdc3-dotnet) project. ([#1108](https://github.com/finos/FDC3/pull/1108)) * The supported platforms page in the FDC3 documentation was moved into the API section as the information it provides all relates to FDC3 Desktop Agent API implementations. ([#1108](https://github.com/finos/FDC3/pull/1108)) ### Deprecated * Made `IntentMetadata.displayName` optional as it is deprecated. ([#1280](https://github.com/finos/FDC3/pull/1280)) +* Deprecated `PrivateChannel`'s synchronous `onAddContextListener`, `onUnsubscribe` and `onDisconnect` functions in favour of an `async` `addEventListener` function consistent with the one added to `DesktopAgent` in #1207. ([#1305](https://github.com/finos/FDC3/pull/1305)) ### Fixed diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 9c452b1f2..4388c8055 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -48,7 +48,7 @@ interface DesktopAgent { leaveCurrentChannel() : Promise; // non-context events - addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise; + addEventListener(type: FDC3EventTypes | null, handler: EventHandler): Promise; //implementation info getInfo(): Promise; @@ -183,7 +183,7 @@ var contactListener = await _desktopAgent.AddContextListener("fdc3.cont ```ts -addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise; +addEventListener(type: FDC3EventTypes | null, handler: EventHandler): Promise; ``` @@ -210,12 +210,11 @@ Whenever the handler function is called it will be passed an event object with d const listener = await fdc3.addEventListener(null, event => { ... }); // listener for a specific event type that logs its details -const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USER_CHANNEL_CHANGED, event => { +const userChannelChangedListener = await fdc3.addEventListener("userChannelChanged ", event => { console.log(`Received event ${event.type}\n\tDetails: ${event.details}`); //do something else with the event }); ``` - @@ -226,6 +225,12 @@ Not implemented +**See also:** + +- [`FDC3EventTypes`](./Events#fdc3eventtypes) +- [`FDC3Event`](./Events#fdc3event) +- [`EventHandler`](./Events#eventhandler) + ### `addIntentListener` diff --git a/docs/api/ref/Events.md b/docs/api/ref/Events.md index c8692018b..3eb89230c 100644 --- a/docs/api/ref/Events.md +++ b/docs/api/ref/Events.md @@ -2,58 +2,152 @@ title: Events --- -In addition to intent and context events, the FDC3 API may be used to listen for other types of events via the `addEventListener()` function. +In addition to intent and context events, the FDC3 API and PrivateChannel API may be used to listen for other types of events via their `addEventListener()` functions. + +## `ApiEvent` + +Type defining a basic event object that may be emitted by an FDC3 API interface such as DesktopAgent or PrivateChannel. There are more specific event types defined for each interface. + +```ts +interface ApiEvent { + readonly type: string; + readonly details: any; +} +``` + +**See also:** + +- [`FDC3Event`](#fdc3event) +- [`PrivateChannelEvent`](#privatechannelevent) ## `EventHandler` ```ts -type EventHandler = (event: FDC3Event) => void; +type EventHandler = (event: ApiEvent) => void; ``` -Describes a callback that handles non-context and non-intent events. Provides the details of the event. +Describes a callback that handles non-context and non-intent events. Provides the details of the event. -Used when attaching listeners to events. +Used when attaching listeners to events. **See also:** -- [`DesktopAgent.addEventListener`](DesktopAgent#addEventListener) -- [`FDC3Event`](#fdc3event) -## `FDC3EventType` +- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener) +- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener) +- [`ApiEvent`](#apievent) + +## `FDC3EventTypes` + ```ts -enum FDC3EventType { - USER_CHANNEL_CHANGED = "USER_CHANNEL_CHANGED" -} +type FDC3EventTypes = "userChannelChanged"; ``` -Enumeration defining the types of (non-context and non-intent) events that may be received via the FDC3 API's `addEventListener` function. +Type defining valid type strings for DesktopAgent interface events. **See also:** -- [`DesktopAgent.addEventListener`](DesktopAgent#addEventListener) + +- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener) ## `FDC3Event` ```ts -interface FDC3Event { - readonly type: FDC3EventType; +interface FDC3Event extends ApiEvent{ + readonly type: FDC3EventTypes; readonly details: any; } ``` -Type representing the format of event objects that may be received via the FDC3 API's `addEventListener` function. Will always include both `type` and `details`, which describe type of the event and any additional details respectively. +Type representing the format of event objects that may be received via the FDC3 API's `addEventListener` function. + +Events will always include both `type` and `details` properties, which describe the type of the event and any additional details respectively. **See also:** -- [`DesktopAgent.addEventListener`](DesktopAgent#addEventListener) -- [`FDC3EventType`](#fdc3eventtype) +- [`DesktopAgent.addEventListener`](DesktopAgent#addeventlistener) +- [`FDC3EventTypes`](#fdc3eventtypes) ### `FDC3ChannelChangedEvent` + ```ts interface FDC3ChannelChangedEvent extends FDC3Event { - readonly type: FDC3EventType.USER_CHANNEL_CHANGED; + readonly type: "userChannelChanged"; readonly details: { currentChannelId: string | null }; } ``` -Type representing the format of USER_CHANNEL_CHANGED events. The identity of the channel joined is provided as `details.currentChannelId`, which will be `null` if the app is no longer joined to any channel. \ No newline at end of file +Type representing the format of `userChannelChanged` events. + +The identity of the channel joined is provided as `details.currentChannelId`, which will be `null` if the app is no longer joined to any channel. + +## `PrivateChannelEventTypes` + +```ts +type PrivateChannelEventTypes = "addContextListener" | "unsubscribe" | "disconnect"; +``` + +Type defining valid type strings for Private Channel events. + +**See also:** + +- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener) + +## `PrivateChannelEvent` + +```ts +interface PrivateChannelEvent extends ApiEvent { + readonly type: PrivateChannelEventTypes; + readonly details: any; +} +``` + +Type defining the format of event objects that may be received via a PrivateChannel's `addEventListener` function. + +**See also:** + +- [`PrivateChannel.addEventListener`](PrivateChannel#addeventlistener) +- [`PrivateChannelEventTypes`](#privatechanneleventtypes) + +### `PrivateChannelAddContextListenerEvent` + +```ts +interface PrivateChannelAddContextListenerEvent extends PrivateChannelEvent { + readonly type: "addContextListener"; + readonly details: { + contextType: string | null + }; +} +``` + +Type defining the format of events representing a context listener being added to the channel (`addContextListener`). Desktop Agents MUST fire this event for each invocation of `addContextListener` on the channel, including those that occurred before this handler was registered (to prevent race conditions). + +The context type of the listener added is provided as `details.contextType`, which will be `null` if all event types are being listened to. + +### `PrivateChannelUnsubscribeEvent` + +```ts +interface PrivateChannelUnsubscribeEvent extends PrivateChannelEvent { + readonly type: "unsubscribe"; + readonly details: { + contextType: string | null + }; +} +``` + +Type defining the format of events representing a context listener removed from the channel (`Listener.unsubscribe()`). Desktop Agents MUST call this when `disconnect()` is called by the other party, for each listener that they had added. + +The context type of the listener removed is provided as `details.contextType`, which will be `null` if all event types were being listened to. + +### `PrivateChannelDisconnectEvent` + +```ts +export interface PrivateChannelDisconnectEvent extends PrivateChannelEvent { + readonly type: "disconnect"; + readonly details: null | undefined; +} +``` + +Type defining the format of events representing a remote app being terminated or is otherwise disconnecting from the PrivateChannel. This event is fired in addition to unsubscribe events that will also be fired for any context listeners the disconnecting app had added. + +No details are provided. diff --git a/docs/api/ref/PrivateChannel.md b/docs/api/ref/PrivateChannel.md index 07168866d..300ff0439 100644 --- a/docs/api/ref/PrivateChannel.md +++ b/docs/api/ref/PrivateChannel.md @@ -15,7 +15,7 @@ Object representing a private context channel, which is intended to support secu It is intended that Desktop Agent implementations: - SHOULD restrict external apps from listening or publishing on this channel. -- MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel. +- MUST prevent `PrivateChannels` from being retrieved via `fdc3.getOrCreateChannel`. - MUST provide the `id` value for the channel as required by the `Channel` interface. @@ -23,11 +23,14 @@ It is intended that Desktop Agent implementations: ```ts interface PrivateChannel extends Channel { - // methods + // functions + addEventListener(type: PrivateChannelEventTypes | null, handler: EventHandler): Promise; + disconnect(): Promise; + + //deprecated functions onAddContextListener(handler: (contextType?: string) => void): Listener; onUnsubscribe(handler: (contextType?: string) => void): Listener; onDisconnect(handler: () => void): Listener; - disconnect(): void; } ``` @@ -59,7 +62,7 @@ interface IPrivateChannel : IChannel, IIntentResult ### 'Server-side' example -The intent app establishes and returns a `PrivateChannel` to the client (who is awaiting `getResult()`). When the client calls `addContextlistener()` on that channel, the intent app receives notice via the handler added with `onAddContextListener()` and knows that the client is ready to start receiving quotes. +The intent app establishes and returns a `PrivateChannel` to the client (who is awaiting `getResult()`). When the client calls `addContextListener()` on that channel, the intent app receives notice via the handler added with `addEventListener()` and knows that the client is ready to start receiving quotes. The Desktop Agent knows that a channel is being returned by inspecting the object returned from the handler (e.g. check constructor or look for private member). @@ -74,22 +77,31 @@ fdc3.addIntentListener("QuoteStream", async (context) => { const symbol = context.id.ticker; // This gets called when the remote side adds a context listener - const addContextListener = channel.onAddContextListener((contextType) => { - // broadcast price quotes as they come in from our quote feed - feed.onQuote(symbol, (price) => { - channel.broadcast({ type: "price", price}); - }); - }); + const addContextListener = channel.addEventListener("addContextListener", + (event: PrivateChannelAddContextListenerEvent) => { + console.log(`remote side added a listener for ${event.contextType}`); + // broadcast price quotes as they come in from our quote feed + feed.onQuote(symbol, (price) => { + channel.broadcast({ type: "price", price}); + }); + } + ); // This gets called when the remote side calls Listener.unsubscribe() - const unsubscribeListener = channel.onUnsubscribe((contextType) => { - feed.stop(symbol); - }); + const unsubscribeListener = channel.addEventListener("unsubscribe", + (event: PrivateChannelUnsubscribeEvent) => { + console.log(`remote side unsubscribed a listener for ${event.contextType}`); + feed.stop(symbol); + } + ); // This gets called if the remote side closes - const disconnectListener = channel.onDisconnect(() => { - feed.stop(symbol); - }); + const disconnectListener = channel.addEventListener("disconnect", + () => { + console.log(`remote side disconnected`); + feed.stop(symbol); + } + ); return channel; }); @@ -141,23 +153,24 @@ Although this interaction occurs entirely in frontend code, we refer to it as th try { const resolution3 = await fdc3.raiseIntent("QuoteStream", { type: "fdc3.instrument", id : { symbol: "AAPL" } }); try { - const result = await resolution3.getResult(); - //check that we got a result and that it's a channel - if (result && result.addContextListener) { - const listener = result.addContextListener("price", (quote) => console.log(quote)); - - //if it's a PrivateChannel - if (result.onDisconnect) { - result.onDisconnect(() => { - console.warn("Quote feed went down"); - }); + const result = await resolution3.getResult(); + //check that we got a result and that it's a channel + if (result && result.addContextListener) { + const listener = result.addContextListener("price", (quote) => console.log(quote)); + //if it's a PrivateChannel + if (result.type == "private") { + result.addEventListener("disconnect", () => { + console.warn("Quote feed went down"); + }); // Sometime later... - listener.unsubscribe(); - } + await listener.unsubscribe(); + } } else { console.warn(`${resolution3.source} did not return a channel`); } + } catch(channelError) { + console.log(`Error: ${resolution3.source} returned an error: ${channelError}`); } catch(resultError: ResultError) { console.log(`Error: ${resolution3.source} returned an error: ${resultError}`); } @@ -205,107 +218,148 @@ catch (Exception ex) -## Methods +## Functions -### `onAddContextListener` +### `addEventListener` ```ts -onAddContextListener(handler: (contextType?: string) => void): Listener; +addEventListener(type: PrivateChannelEventTypes | null, handler: EventHandler): Promise; ``` ```csharp -IListener OnAddContextListener(Action handler); +Not implemented ``` -Adds a listener that will be called each time that the remote app invokes addContextListener on this channel. -Desktop Agents MUST call this for each invocation of addContextListener on this channel, including those that occurred before this handler was registered (to prevent race conditions). +Register a handler for events from the PrivateChannel. Whenever the handler function is called it will be passed an event object with details related to the event. -**See also:** + + -- [`Channel.addContextListener`](Channel#addcontextlistener) +```ts +// any event type +const listener: Listener = await myPrivateChannel.addEventListener(null, + (event: PrivateChannelEvent) => { + console.log(`Received event ${event.type}\n\tDetails: ${event.details}`); + } +); +``` -### `onUnsubscribe` + + + +```csharp +Not implemented +``` + + + + +**See also:** + +- [Events](./Events) +- [EventHandler](./Events#eventhandler) +- [PrivateChannelEvent](./Events#privatechannelevent) +- [PrivateChannelAddContextListenerEvent](./Events#privatechanneladdcontextlistenerevent) +- [PrivateChannelUnsubscribeEvent](./Events#privatechannelunsubscribeevent) +- [PrivateChannelDisconnectEvent](./Events#privatechanneldisconnectevent) + +### `disconnect` ```ts -onUnsubscribe(handler: (contextType?: string) => void): Listener; +disconnect(): Promise; ``` ```csharp -IListener OnUnsubscribe(Action handler); +void Disconnect(); ``` -Adds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added. + +May be called to indicate that a participant will no longer interact with this channel. -Desktop Agents MUST call this when disconnect() is called by the other party, for each listener that they had added. +## Deprecated Functions -**See also:** +### `onAddContextListener` -- [`Listener`](Types#listener) + + -### `onDisconnect` +```ts +onAddContextListener(handler: (contextType?: string) => void): Listener; +``` + + + + +```csharp +IListener OnAddContextListener(Action handler); +``` + + + + +Deprecated in favour of the async `addEventListener("addContextListener", handler)` function. + +Adds a listener that will be called each time that the remote app invokes addContextListener on this channel. + +### `onUnsubscribe` ```ts -onDisconnect(handler: () => void): Listener; +onUnsubscribe(handler: (contextType?: string) => void): Listener; ``` - + ```csharp -IListener OnDisconnect(Action handler); +IListener OnUnsubscribe(Action handler); ``` -Adds a listener that will be called when the remote app terminates, for example when its window is closed or because disconnect was called. This is in addition to calls that will be made to onUnsubscribe listeners. -**See also:** +Deprecated in favour of the async `addEventListener("unsubscribe", handler)` function. -- [`disconnect`](#disconnect) +Adds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added. -### `disconnect` +### `onDisconnect` ```ts -disconnect(): void; +onDisconnect(handler: () => void): Listener; ``` ```csharp -void Disconnect(); +IListener OnDisconnect(Action handler); ``` -May be called to indicate that a participant will no longer interact with this channel. - -After this function has been called, Desktop Agents SHOULD prevent apps from broadcasting on this channel and MUST automatically call Listener.unsubscribe() for each listener that they've added (causing any `onUnsubscribe` handler added by the other party to be called) before triggering any onDisconnect handler added by the other party. -**See also:** +Deprecated in favour of the async `addEventListener("disconnect", handler)` function. -- [`onUnsubscribe`](#onunsubscribe) -- [`Listener`](Types#listener) +Adds a listener that will be called when the remote app terminates, for example when its window is closed or because disconnect was called. diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 16126d5ec..d77f942ab 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -254,14 +254,14 @@ Represented as a union type in TypeScript, however, this type may be rendered as ## `Listener` -A Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener) or [`addContextListener`](DesktopAgent#addcontextlistener) methods on the [DesktopAgent](DesktopAgent) object. +A Listener object is returned when an application subscribes to intents or context broadcasts via the [`addIntentListener`](DesktopAgent#addintentlistener), [`addContextListener`](DesktopAgent#addcontextlistener) or [`addEventListener`](DesktopAgent#addeventlistener) on the [DesktopAgent](DesktopAgent) object or (PrivateChannel#addeventlistener) on the [PrivateChannel](PrivateChannel) object. ```ts interface Listener { - unsubscribe(): void; + unsubscribe(): Promise; } ``` @@ -284,7 +284,7 @@ interface IListener ```ts -unsubscribe(): void; +unsubscribe(): Promise; ``` diff --git a/docs/context/ref/ChatRoom.md b/docs/context/ref/ChatRoom.md index 14a5924a5..fbd2d8c04 100644 --- a/docs/context/ref/ChatRoom.md +++ b/docs/context/ref/ChatRoom.md @@ -1,6 +1,7 @@ --- title: ChatRoom sidebar_label: ChatRoom + --- # ChatRoom diff --git a/src/api/DesktopAgent.ts b/src/api/DesktopAgent.ts index 59be809df..b31289d74 100644 --- a/src/api/DesktopAgent.ts +++ b/src/api/DesktopAgent.ts @@ -15,7 +15,7 @@ import { AppIdentifier } from './AppIdentifier'; import { AppMetadata } from './AppMetadata'; import { Intent } from '../intents/Intents'; import { ContextType } from '../context/ContextType'; -import { EventHandler, FDC3EventType } from './Events'; +import { EventHandler, FDC3EventTypes } from './Events'; /** * A Desktop Agent is a desktop component (or aggregate of components) that serves as a @@ -385,7 +385,7 @@ export interface DesktopAgent { * const listener = await fdc3.addEventListener(null, event => { ... }); * * // listener for a specific event type that logs its details - * const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USER_CHANNEL_CHANGED, event => { + * const userChannelChangedListener = await fdc3.addEventListener("userChannelChanged", event => { * console.log(`Received event ${event.type}\n\tDetails: ${event.details}`); * //do something else with the event * }); @@ -395,7 +395,7 @@ export interface DesktopAgent { * @param {EventHandler} handler A function that events received will be passed to. * */ - addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise; + addEventListener(type: FDC3EventTypes | null, handler: EventHandler): Promise; /** * Retrieves a list of the User channels available for the app to join. diff --git a/src/api/Events.ts b/src/api/Events.ts index e0f003dac..bf507d74f 100644 --- a/src/api/Events.ts +++ b/src/api/Events.ts @@ -3,36 +3,102 @@ * Copyright FINOS FDC3 contributors - see NOTICE file */ -/** Type representing a handler function for events from the Desktop Agent. - * @param {FDC3Event} event The handler function will be passed an `FDC3Event` Object - * providing details of the event (such as a change of channel membership for the app) as the only - * parameter. +/** + * Type defining a basic event object that may be emitted by an FDC3 API interface + * such as DesktopAgent or PrivateChannel. There are more specific event types + * defined for each interface. + */ +export interface ApiEvent { + readonly type: string; + readonly details: any; +} + +/** Type representing a handler function for events from the Desktop Agent + * or a PrivateChannel. + * @param event The handler function will be passed an `ApiEvent` (or more specifically + * an `FDC3Event` or `PrivateChannelEvent`) Object providing details of the event (such + * as a change of channel membership for the app, or type of context listener added) + * as the only parameter. */ -export type EventHandler = (event: FDC3Event) => void; +export type EventHandler = (event: ApiEvent ) => void; /** - * Enumeration defining the types of (non-context and non-intent) events that may be received - via the FDC3 API's `addEventListener` function. + * Type defining valid type strings for DesktopAgent interface events. */ -export enum FDC3EventType { - USER_CHANNEL_CHANGED = "USER_CHANNEL_CHANGED" -} +export type FDC3EventTypes = "userChannelChanged"; + /** - * Type representing the format of event objects that may be received - via the FDC3 API's `addEventListener` function. + * Type defining the format of event objects that may be received + * via the FDC3 API's `addEventListener` function. */ -export interface FDC3Event { - readonly type: FDC3EventType; +export interface FDC3Event extends ApiEvent { + readonly string: FDC3EventTypes; readonly details: any; } /** - * Type representing the format of event USER_CHANNEL_CHANGED objects + * Type defining the format of event `userChannelChanged` objects */ export interface FDC3ChannelChangedEvent extends FDC3Event { - readonly type: FDC3EventType.USER_CHANNEL_CHANGED; + readonly type: "userChannelChanged"; readonly details: { currentChannelId: string | null }; -} \ No newline at end of file +} + +/** + * Type defining valid type strings for Private Channel events. + */ +export type PrivateChannelEventTypes = "addContextListener" | "unsubscribe" | "disconnect"; + +/** + * Type defining the format of event objects that may be received + * via a PrivateChannel's `addEventListener` function. + */ +export interface PrivateChannelEvent { + readonly type: PrivateChannelEventTypes; + readonly details: any; +} + +/** + * Type defining the format of events representing a context listener being + * added to the channel (`addContextListener`). Desktop Agents MUST fire this + * event for each invocation of `addContextListener` on the channel, including + * those that occurred before this handler was registered (to prevent race + * conditions). + * The context type of the listener added is provided as `details.contextType`, + * which will be `null` if all event types are being listened to. + */ +export interface PrivateChannelAddContextListenerEvent extends PrivateChannelEvent { + readonly type: "addContextListener"; + readonly details: { + contextType: string | null + }; +} + +/** + * Type defining the format of events representing a context listener + * removed from the channel (`Listener.unsubscribe()`). Desktop Agents MUST call + * this when `disconnect()` is called by the other party, for each listener that + * they had added. + * The context type of the listener removed is provided as `details.contextType`, + * which will be `null` if all event types were being listened to. + */ +export interface PrivateChannelUnsubscribeEvent extends PrivateChannelEvent { + readonly type: "unsubscribe"; + readonly details: { + contextType: string | null + }; +} + +/** + * Type defining the format of events representing a remote app being terminated + * or otherwise disconnecting from the PrivateChannel. This event is in addition to + * unsubscribe events that will also be fired for any context listeners they had added. + * No details are provided. + */ +export interface PrivateChannelDisconnectEvent extends PrivateChannelEvent { + readonly type: "disconnect"; + readonly details: null | undefined; +} diff --git a/src/api/Listener.ts b/src/api/Listener.ts index ced9e2e31..267da7e72 100644 --- a/src/api/Listener.ts +++ b/src/api/Listener.ts @@ -7,5 +7,5 @@ export interface Listener { /** * Unsubscribe the listener object. */ - unsubscribe(): void; + unsubscribe(): Promise; } diff --git a/src/api/PrivateChannel.ts b/src/api/PrivateChannel.ts index a2036b21a..f9a15fa09 100644 --- a/src/api/PrivateChannel.ts +++ b/src/api/PrivateChannel.ts @@ -5,6 +5,7 @@ import { Listener } from './Listener'; import { Channel } from './Channel'; +import { EventHandler, PrivateChannelEventTypes } from './Events'; /** * Object representing a private context channel, which is intended to support @@ -20,7 +21,47 @@ import { Channel } from './Channel'; * - MUST provide the `id` value for the channel as required by the Channel interface. */ export interface PrivateChannel extends Channel { + + /** + * Register a handler for events from the PrivateChannel. Whenever the handler function + * is called it will be passed an event object with details related to the event. + * + * ```js + * // any event type + * const listener = await myPrivateChannel.addEventListener(null, event => { + * console.log(`Received event ${event.type}\n\tDetails: ${event.details}`); + * }); + * + * // listener for a specific event type + * const channelChangedListener = await myPrivateChannel.addEventListener( + * "addContextListener", + * event => { ... } + * ); + * ``` + * + * @param {PrivateChannelEventType | null} type If non-null, only events of the specified type will be received by the handler. + * @param {EventHandler} handler A function that events received will be passed to. + * + */ + addEventListener(type: PrivateChannelEventTypes | null, handler: EventHandler): Promise; + + /** + * May be called to indicate that a participant will no longer interact with this channel. + * + * After this function has been called, Desktop Agents SHOULD prevent apps from broadcasting + * on this channel and MUST automatically call Listener.unsubscribe() for each listener that + * they've added (causing any onUnsubscribe handler added by the other party to be called) + * before triggering any onDisconnect handler added by the other party. + */ + disconnect(): Promise; + + //--------------------------------------------------------------------------------------------- + //Deprecated function signatures + //--------------------------------------------------------------------------------------------- + /** + * @deprecated use `addEventListener("addContextListener", handler)` instead. + * * Adds a listener that will be called each time that the remote app invokes * addContextListener on this channel. * @@ -31,6 +72,8 @@ export interface PrivateChannel extends Channel { onAddContextListener(handler: (contextType?: string) => void): Listener; /** + * @deprecated use `addEventListener("unsubscribe", handler)` instead. + * * Adds a listener that will be called whenever the remote app invokes * Listener.unsubscribe() on a context listener that it previously added. * @@ -40,19 +83,11 @@ export interface PrivateChannel extends Channel { onUnsubscribe(handler: (contextType?: string) => void): Listener; /** + * @deprecated use `addEventListener("disconnect", handler)` instead. + * * Adds a listener that will be called when the remote app terminates, for example * when its window is closed or because disconnect was called. This is in addition * to calls that will be made to onUnsubscribe listeners. */ onDisconnect(handler: () => void): Listener; - - /** - * May be called to indicate that a participant will no longer interact with this channel. - * - * After this function has been called, Desktop Agents SHOULD prevent apps from broadcasting - * on this channel and MUST automatically call Listener.unsubscribe() for each listener that - * they've added (causing any onUnsubscribe handler added by the other party to be called) - * before triggering any onDisconnect handler added by the other party. - */ - disconnect(): void; } diff --git a/src/context/ContextTypes.ts b/src/context/ContextTypes.ts index 8b8c0d45a..8fccd9007 100644 --- a/src/context/ContextTypes.ts +++ b/src/context/ContextTypes.ts @@ -258,35 +258,35 @@ export interface InstrumentElement { */ export interface PurpleInstrumentIdentifiers { /** - * + * https://www.bloomberg.com/ */ BBG?: string; /** - * + * https://www.cusip.com/ */ CUSIP?: string; /** - * + * https://www.factset.com/ */ FDS_ID?: string; /** - * + * https://www.openfigi.com/ */ FIGI?: string; /** - * + * https://www.isin.org/ */ ISIN?: string; /** - * + * https://permid.org/ */ PERMID?: string; /** - * + * https://www.refinitiv.com/ */ RIC?: string; /** - * + * https://www.lseg.com/sedol */ SEDOL?: string; /** @@ -303,15 +303,15 @@ export interface PurpleInstrumentIdentifiers { */ export interface OrganizationMarket { /** - * + * https://www.bloomberg.com/ */ BBG?: string; /** - * + * https://www.iso.org/iso-3166-country-codes.html */ COUNTRY_ISOALPHA2?: string; /** - * + * https://en.wikipedia.org/wiki/Market_Identifier_Code */ MIC?: string; /** @@ -798,15 +798,15 @@ export interface OrganizationObject { */ export interface Identifiers { /** - * + * https://www.bloomberg.com/ */ BBG?: string; /** - * + * https://www.cusip.com/ */ CUSIP?: string; /** - * + * https://www.factset.com/ * * FactSet Permanent Identifier representing the organization * @@ -814,25 +814,25 @@ export interface Identifiers { */ FDS_ID?: string; /** - * + * https://www.openfigi.com/ */ FIGI?: string; /** - * + * https://www.isin.org/ */ ISIN?: string; /** - * + * https://permid.org/ * * Refinitiv Permanent Identifiers, or PermID for the organization */ PERMID?: string; /** - * + * https://www.refinitiv.com/ */ RIC?: string; /** - * + * https://www.lseg.com/sedol */ SEDOL?: string; /** @@ -1181,35 +1181,35 @@ export interface Instrument { */ export interface FluffyInstrumentIdentifiers { /** - * + * https://www.bloomberg.com/ */ BBG?: string; /** - * + * https://www.cusip.com/ */ CUSIP?: string; /** - * + * https://www.factset.com/ */ FDS_ID?: string; /** - * + * https://www.openfigi.com/ */ FIGI?: string; /** - * + * https://www.isin.org/ */ ISIN?: string; /** - * + * https://permid.org/ */ PERMID?: string; /** - * + * https://www.refinitiv.com/ */ RIC?: string; /** - * + * https://www.lseg.com/sedol */ SEDOL?: string; /** @@ -1226,15 +1226,15 @@ export interface FluffyInstrumentIdentifiers { */ export interface PurpleMarket { /** - * + * https://www.bloomberg.com/ */ BBG?: string; /** - * + * https://www.iso.org/iso-3166-country-codes.html */ COUNTRY_ISOALPHA2?: string; /** - * + * https://en.wikipedia.org/wiki/Market_Identifier_Code */ MIC?: string; /** diff --git a/src/index.ts b/src/index.ts index 3c1665350..3a2d997db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,9 @@ import { DesktopAgent } from './api/DesktopAgent'; import * as BridgingTypes from './bridging/BridgingTypes'; -export * from './api/AppIdentifier'; +export * from './context/ContextTypes'; +//explicit overwrite of conflicting & equivalent export from ContextTypes +export {AppIdentifier} from './api/AppIdentifier'; export * from './api/AppIntent'; export * from './api/AppMetadata'; export * from './api/Channel'; @@ -25,7 +27,6 @@ export * from './api/PrivateChannel'; export * from './api/RecommendedChannels'; export * from './api/Types'; export * from './context/ContextType'; -export * from './context/ContextTypes'; export * from './intents/Intents'; export * from './api/Events'