From edd07409c2af7ac2b41bc528f9d47a3a31cb54b7 Mon Sep 17 00:00:00 2001 From: Kris West Date: Wed, 15 Nov 2023 17:46:50 +0000 Subject: [PATCH 01/21] Adding tabs throughout API spec for .NET ignatures, moving supported platforms and API access content under API --- docs/api/ref/Channel.md | 177 +++++++- docs/api/ref/DesktopAgent.md | 593 +++++++++++++++++++++++++- docs/api/ref/Errors.md | 78 +++- docs/api/ref/Globals.md | 64 --- docs/api/ref/Metadata.md | 173 +++++++- docs/api/ref/PrivateChannel.md | 98 ++++- docs/api/ref/Types.md | 119 +++++- docs/api/spec.md | 18 +- docs/{ => api}/supported-platforms.md | 28 +- website/docusaurus.config.js | 2 +- website/sidebars.json | 3 +- 11 files changed, 1230 insertions(+), 123 deletions(-) delete mode 100644 docs/api/ref/Globals.md rename docs/{ => api}/supported-platforms.md (78%) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index 0bd65aefb..e6c6a47d3 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -4,6 +4,10 @@ sidebar_label: Channel title: Channel hide_title: true --- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # `Channel` Represents a context channel that applications can join to share context data and provides functions for interacting with it. @@ -18,6 +22,9 @@ There are differences in behavior when you interact with a User channel via the Channels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications. + + + ```ts interface Channel { // properties @@ -38,6 +45,16 @@ interface Channel { } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Context`](Types#context) @@ -50,26 +67,65 @@ interface Channel { ### `id` + + + ```ts public readonly id: string; ``` + + + +```csharp +TBC +``` + + + + Uniquely identifies the channel. It is either assigned by the desktop agent (User Channel) or defined by an application (App Channel). ### `type` + + + ```ts public readonly type: "user" | "app" | "private"; ``` + + + +```csharp +TBC +``` + + + + Can be _user_, _app_ or _private_. ### `displayMetadata` + + + ```ts public readonly displayMetadata?: DisplayMetadata; ``` + + + +```csharp +TBC +``` + + + + DisplayMetadata can be used to provide display hints for User Channels intended to be visualized and selectable by end users. **See also:** @@ -80,10 +136,23 @@ DisplayMetadata can be used to provide display hints for User Channels intended ### `addContextListener` + + + ```ts public addContextListener(contextType: string | null, handler: ContextHandler): Promise; ``` + + + +```csharp +TBC +``` + + + + Adds a listener for incoming contexts of the specified _context type_ whenever a broadcast happens on this channel. If, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the [`getCurrentContext(contextType)`](#getcurrentcontext) function. @@ -94,6 +163,9 @@ Optional metadata about each context message received, including the app that or Add a listener for any context that is broadcast on the channel: + + + ```ts const listener = await channel.addContextListener(null, context => { if (context.type === 'fdc3.contact') { @@ -107,8 +179,21 @@ const listener = await channel.addContextListener(null, context => { listener.unsubscribe(); ``` + + + +```csharp +TBC +``` + + + + Adding listeners for specific types of context that is broadcast on the channel: + + + ```ts const contactListener = await channel.addContextListener('fdc3.contact', contact => { // handle the contact @@ -123,6 +208,16 @@ contactListener.unsubscribe(); instrumentListener.unsubscribe(); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Listener`](Types#listener) @@ -132,10 +227,23 @@ instrumentListener.unsubscribe(); ### `broadcast` -```typescript + + + +```ts public broadcast(context: Context): Promise; ``` + + + +```csharp +TBC +``` + + + + Broadcasts a context on the channel. This function can be used without first joining the channel, allowing applications to broadcast on both App Channels and User Channels that they aren't a member of. If the broadcast is denied by the channel or the channel is not available, the promise will be rejected with an `Error` with a `message` string from the [`ChannelError`](Errors#channelerror) enumeration. @@ -148,7 +256,10 @@ If an application attempts to broadcast an invalid context argument the Promise **Example:** -```javascript + + + +```ts const instrument = { type: 'fdc3.instrument', id: { @@ -163,6 +274,16 @@ try { } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`ChannelError`](Errors#channelerror) @@ -171,10 +292,23 @@ try { ### `getCurrentContext` + + + ```ts public getCurrentContext(contextType?: string): Promise; ``` + + + +```csharp +TBC +``` + + + + When a _context type_ is provided, the most recent context matching the type will be returned, or `null` if no matching context is found. If no _context type_ is provided, the most recent context that was broadcast on the channel - regardless of type - will be returned. If no context has been set on the channel, it will return `null`. @@ -187,6 +321,9 @@ If getting the current context fails, the promise will be rejected with an `Erro Without specifying a context type: + + + ```ts try { const context = await channel.getCurrentContext(); @@ -195,8 +332,21 @@ try { } ``` + + + +```csharp +TBC +``` + + + + Specifying a context type: + + + ```ts try { const contact = await channel.getCurrentContext('fdc3.contact'); @@ -205,6 +355,16 @@ try { } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`ChannelError`](Errors#channelerror) @@ -215,6 +375,9 @@ try { ### `addContextListener` (deprecated) + + + ```ts /** * @deprecated Use `addContextListener(null, handler)` instead of `addContextListener(handler)` @@ -222,6 +385,16 @@ try { public addContextListener(handler: ContextHandler): Promise; ``` + + + +```csharp +TBC +``` + + + + Adds a listener for incoming contexts whenever a broadcast happens on the channel. **See also:** diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 991047cb5..4f660deb5 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -4,13 +4,20 @@ sidebar_label: DesktopAgent title: DesktopAgent hide_title: true --- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # `DesktopAgent` An FDC3 Desktop Agent is a desktop component (or aggregate of components) that serves as an orchestrator for applications in its domain. A Desktop Agent can be connected to one or more App Directories and will use directories for application identity and discovery. Typically, a Desktop Agent will contain the proprietary logic of a given platform, handling functionality like explicit application interop workflows where security, consistency, and implementation requirements are proprietary. -It is expected that the `DesktopAgent` interface is made available via the [`window.fdc3`](Globals#windowfdc3-object) global object, and that the [`fdc3Ready`](Globals#fdc3ready-event) event fires when it is ready to be used. +For details of how implementations of the `DesktopAgent` are made available to applications please see [Supported Platforms](supported-platforms). + + + ```ts interface DesktopAgent { @@ -53,14 +60,37 @@ interface DesktopAgent { } ``` + + + +```csharp +TBC +``` + + + + ## Functions ### `addContextListener` + + + ```ts addContextListener(contextType: string | null, handler: ContextHandler): Promise; ``` + + + +```csharp +TBC +``` + + + + Adds a listener for incoming context broadcasts from the Desktop Agent (via a User channel or [`fdc3.open`](#open) API call). 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. Context broadcasts are primarily received from apps that are joined to the same User Channel as the listening application, hence, if the application is not currently joined to a User Channel no broadcasts will be received from channels. If this function is called after the app has already joined a channel and the channel already contains context that would be passed to the context listener, then it will be called immediately with that context. @@ -71,6 +101,9 @@ Optional metadata about each context message received, including the app that or **Examples:** + + + ```js // any context const listener = await fdc3.addContextListener(null, context => { ... }); @@ -85,6 +118,16 @@ const contactListener = await fdc3.addContextListener('fdc3.contact', (contact, }); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Listener`](Types#listener) @@ -93,10 +136,23 @@ const contactListener = await fdc3.addContextListener('fdc3.contact', (contact, ### `addIntentListener` + + + ```ts addIntentListener(intent: string, handler: IntentHandler): Promise; ``` + + + +```csharp +TBC +``` + + + + Adds a listener for incoming intents raised by other applications, via calls to [`fdc3.raiseIntent`](#raiseintent) or [`fdc3.raiseIntentForContext`](#raiseintentforcontext). If the application is intended to be launched to resolve raised intents, it SHOULD add its intent listeners as quickly as possible after launch or an error MAY be returned to the caller and the intent and context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds. The handler function may return void or a promise that resolves to a [`IntentResult`](Types#intentresult), which is either a [`Context`](Types#context) object, representing any data that should be returned to the app that raised the intent, or a [`Channel`](Channel), a [`PrivateChannel`](PrivateChannel) over which data responses will be sent, or `void`. The `IntentResult` will be returned to the app that raised the intent via the [`IntentResolution`](Metadata#intentresolution) and retrieved from it using the `getResult()` function. @@ -113,6 +169,9 @@ Optional metadata about each intent & context message received, including the ap **Examples:** + + + ```js //Handle a raised intent const listener = fdc3.addIntentListener('StartChat', context => { @@ -156,6 +215,16 @@ fdc3.addIntentListener("QuoteStream", async (context) => { }); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [Register an Intent Handler](../spec#register-an-intent-handler) @@ -166,10 +235,23 @@ fdc3.addIntentListener("QuoteStream", async (context) => { ### `broadcast` + + + ```ts broadcast(context: Context): Promise; ``` + + + +```csharp +TBC +``` + + + + Publishes context to other apps on the desktop. Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever _User 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. DesktopAgent implementations SHOULD ensure that context messages broadcast to a channel by an application joined to it are not delivered back to that same application. @@ -180,6 +262,9 @@ If an application attempts to broadcast an invalid context argument the Promise **Example:** + + + ```js const instrument = { type: 'fdc3.instrument', @@ -191,16 +276,39 @@ const instrument = { fdc3.broadcast(instrument); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [addContextListener](#addcontextlistener) ### `createPrivateChannel` + + + ```ts createPrivateChannel(): Promise; ``` + + + +```csharp +TBC +``` + + + + Returns a `Channel` with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent. If the `PrivateChannel` cannot be created, the returned promise MUST be rejected with an `Error` object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration. @@ -215,6 +323,9 @@ It is intended that Desktop Agent implementations: **Example:** + + + ```js fdc3.addIntentListener("QuoteStream", async (context) => { const channel = await fdc3.createPrivateChannel(); @@ -242,6 +353,16 @@ fdc3.addIntentListener("QuoteStream", async (context) => { }); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`PrivateChannel`](PrivateChannel) @@ -250,10 +371,23 @@ fdc3.addIntentListener("QuoteStream", async (context) => { ### `findInstances` + + + ```ts findInstances(app: AppIdentifier): Promise>; ``` + + + +```csharp +TBC +``` + + + + Find all the available instances for a particular application. If the application is not known to the agent, the returned promise should be rejected with the `ResolverError.NoAppsFound` error message. However, if the application is known but there are no instances of the specified app the returned promise should resolve to an empty array. @@ -262,6 +396,9 @@ If the request fails for another reason, the promise MUST be rejected with an `E **Example:** + + + ```js // Retrieve a list of instances of an application let instances = await fdc3.findInstances({appId: "MyAppId"}); @@ -270,12 +407,35 @@ let instances = await fdc3.findInstances({appId: "MyAppId"}); let resolution = fdc3.raiseIntent("ViewInstrument", context, instances[0]); ``` + + + +```csharp +TBC +``` + + + + ### `findIntent` + + + ```ts findIntent(intent: string, context?: Context, resultType?: string): Promise; ``` + + + +```csharp +TBC +``` + + + + Find out more information about a particular intent by passing its name, and optionally its context and/or a desired result context type. `findIntent` is effectively granting programmatic access to the Desktop Agent's resolver. @@ -289,6 +449,9 @@ Result types may be a type name, the string `"channel"` (which indicates that th I know 'StartChat' exists as a concept, and want to know which apps can resolve it: + + + ```js const appIntent = await fdc3.findIntent("StartChat"); // returns a single AppIntent: @@ -318,8 +481,21 @@ const appIntent = await fdc3.findIntent("StartChat"); // ] ``` + + + +```csharp +TBC +``` + + + + An optional input context object and/or `resultType` argument may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types. + + + ```js const appIntent = await fdc3.findIntent("StartChat", contact); @@ -344,16 +520,39 @@ const appIntent = await fdc3.findIntent("QuoteStream", instrument, "channel + + +```csharp +TBC +``` + + + + **See also:** - [`ResolveError`](Errors#resolveerror) ### `findIntentsByContext` + + + ```ts findIntentsByContext(context: Context, resultType?: string): Promise>; ``` + + + +```csharp +TBC +``` + + + + Find all the available intents for a particular context, and optionally a desired result context type. `findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver. @@ -367,6 +566,9 @@ The optional `resultType` argument may be a type name, the string `"channel"` (w I have a context object, and I want to know what I can do with it, hence, I look for intents and apps to resolve them... + + + ```js const appIntents = await fdc3.findIntentsByContext(context); @@ -392,8 +594,21 @@ const appIntents = await fdc3.findIntentsByContext(context); // ]; ``` + + + +```csharp +TBC +``` + + + + or I look for only intents that are resolved by apps returning a particular result type + + + ```js const appIntentsForType = await fdc3.findIntentsByContext(context, "fdc3.ContactList"); // returns for example: @@ -412,6 +627,16 @@ const selectedApp = startChat.apps[2]; await fdc3.raiseIntent(startChat.intent.name, context, selectedApp); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`findIntent()`](#findintent) @@ -419,22 +644,47 @@ await fdc3.raiseIntent(startChat.intent.name, context, selectedApp); ### `getAppMetadata` + + + ```ts getAppMetadata(app: AppIdentifier): Promise; ``` + + + +```csharp +TBC +``` + + + + Retrieves the [`AppMetadata`](Metadata#appmetadata) for an [`AppIdentifier`](Types#appidentifier), which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes. If the app is not found, the promise MUST be rejected with an `Error` Object with the `message` given by [`ResolveError.TargetAppUnavailable`](Errors#resolveerror), or (if connected to a Desktop Agent Bridge) an error from the [`BridgingError`](Errors#bridgingerror) enumeration. +**Example:** -**Examples:** + + ```js let appIdentifier = { appId: "MyAppId@my.appd.com" } let appMetadata = await fdc3.getAppMetadata(appIdentifier); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`AppMetadata`](Metadata#appmetadata) @@ -442,37 +692,79 @@ let appMetadata = await fdc3.getAppMetadata(appIdentifier); ### `getCurrentChannel` + + + ```ts getCurrentChannel() : Promise; ``` + + + +```csharp +TBC +``` + + + + OPTIONAL function that returns the `Channel` object for the current User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly. Returns `null` if the app is not joined to a channel. -**Examples:** +**Example:** + + + ```js // get the current channel membership let current = await fdc3.getCurrentChannel(); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Channel`](Channel) ### `getInfo` + + + ```ts getInfo(): Promise; ``` + + + +```csharp +TBC +``` + + + + Retrieves information about the FDC3 Desktop Agent implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent. Returns an [`ImplementationMetadata`](Metadata#implementationmetadata) object. This metadata object can be used to vary the behavior of an application based on the version supported by the Desktop Agent and for logging purposes. **Example:** + + + ```js import {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3'; @@ -483,13 +775,36 @@ if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), "1.2")) { } ``` + + + +```csharp +TBC +``` + + + + The `ImplementationMetadata` object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.: + + + ```js let implementationMetadata = await fdc3.getInfo(); let {appId, instanceId} = implementationMetadata.appMetadata; ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`ImplementationMetadata`](Metadata#implementationmetadata) @@ -497,55 +812,120 @@ let {appId, instanceId} = implementationMetadata.appMetadata; ### `getOrCreateChannel` + + + ```ts getOrCreateChannel(channelId: string): Promise; ``` + + + +```csharp +TBC +``` + + + + Returns a `Channel` object for the specified channel, creating it (as an _App_ channel) if it does not exist. If the Channel cannot be created or access was denied, the returned promise MUST be rejected with an `Error` Object with a `message` chosen from the `ChannelError` enumeration. **Example:** -```js + + + +```ts try { const myChannel = await fdc3.getOrCreateChannel("myChannel"); myChannel.addContextListener(null, context => { /* do something with context */}); } -catch (err){ +catch (err: ChannelError) { //app could not register the channel } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Channel`](Channel) ### `getUserChannels` + + + ```ts getUserChannels() : Promise>; ``` + + + +```csharp +TBC +``` + + + + Retrieves a list of the User Channels available for the app to join. **Example:** + + + ```js const userChannels = await fdc3.getUserChannels(); const redChannel = userChannels.find(c => c.id === 'red'); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Channel`](Channel) ### `joinUserChannel` + + + ```ts joinUserChannel(channelId: string) : Promise; ``` + + + +```csharp +TBC +``` + + + + OPTIONAL function that joins the app to the specified User channel. In most cases, applications SHOULD be joined to channels via UX provided to the application by the desktop agent, rather than calling this function directly. If an app is joined to a channel, all `fdc3.broadcast` calls will go to the channel, and all listeners assigned via `fdc3.addContextListener` will listen on the channel. @@ -556,7 +936,10 @@ An app can only be joined to one channel at a time. If an error occurs (such as the channel is unavailable or the join request is denied) the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ChannelError`](Errors#channelerror) enumeration. -**Examples:** +**Example:** + + + ```js // get all user channels @@ -566,24 +949,49 @@ const channels = await fdc3.getUserChannels(); // join the channel on selection fdc3.joinUserChannel(selectedChannel.id); +``` + + + +```csharp +TBC ``` + + + **See also:** - [`getUserChannels`](#getuserchannels) ### `leaveCurrentChannel` + + + ```ts leaveCurrentChannel() : Promise; ``` + + + +```csharp +TBC +``` + + + + OPTIONAL function that removes the app from any User channel membership. In most cases, an application's membership of channels SHOULD be managed via UX provided to the application by the desktop agent, rather than calling this function directly. Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be a no-op when the app is not joined to a User channel. -**Examples:** +**Example:** + + + ```js //desktop-agent scope context listener @@ -597,12 +1005,35 @@ redChannel.addContextListener(null, channelListener); ``` + + + +```csharp +TBC +``` + + + + ### `open` + + + ```ts open(app: AppIdentifier, context?: Context): Promise; ``` + + + +```csharp +TBC +``` + + + + Launches an app, specified via an [`AppIdentifier`](Types#appidentifier) object. The `open` method differs in use from [`raiseIntent`](#raiseintent). Generally, it should be used when the target application is known but there is no specific intent. For example, if an application is querying an App Directory, `open` would be used to open an app returned in the search results. @@ -617,6 +1048,9 @@ If an error occurs while opening the app, the promise MUST be rejected with an ` **Example:** + + + ```js // Open an app without context, using an AppIdentifier object to specify the target let appIdentifier = { appId: 'myApp-v1.0.1' }; @@ -626,6 +1060,16 @@ let instanceIdentifier = await fdc3.open(appIdentifier); let instanceIdentifier = await fdc3.open(appIdentifier, context); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`Context`](Types#context) @@ -635,10 +1079,23 @@ let instanceIdentifier = await fdc3.open(appIdentifier, context); ### `raiseIntent` + + + ```ts raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise; ``` + + + +```csharp +TBC +``` + + + + Raises a specific intent for resolution against apps registered with the desktop agent. 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, a method for resolving the intent to a target app, such as presenting the user with a resolver UI allowing them to pick an app, SHOULD be provided. @@ -654,7 +1111,10 @@ Issuing apps may optionally wait on the promise that is returned by the `getResu **Example:** -```js + + + +```ts // 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 @@ -680,11 +1140,22 @@ try { } else { console.error(`${resolution.source} didn't return anything` } -} catch(error) { +} +catch (error: ResultError) { console.error(`${resolution.source} returned a result error: ${error}`); } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [Raising Intents](../spec#raising-intents) @@ -697,10 +1168,23 @@ try { ### `raiseIntentForContext` + + + ```ts raiseIntentForContext(context: Context, app?: AppIdentifier): Promise; ``` + + + +```csharp +TBC +``` + + + + 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. @@ -714,6 +1198,9 @@ If a target intent and app cannot be found with the criteria provided or the use **Example:** + + + ```js // Display a resolver UI for the user to select an intent and application to resolve it const intentResolution = await fdc3.raiseIntentForContext(context); @@ -722,6 +1209,16 @@ const intentResolution = await fdc3.raiseIntentForContext(context); await fdc3.raiseIntentForContext(context, targetAppIdentifier); ``` + + + +```csharp +TBC +``` + + + + **See also:** - [Raising Intents](../spec#raising-intents) @@ -735,10 +1232,23 @@ await fdc3.raiseIntentForContext(context, targetAppIdentifier); ### `addContextListener` (deprecated) + + + ```ts addContextListener(handler: ContextHandler): Promise; ``` + + + +```csharp +TBC +``` + + + + Adds a listener for incoming context broadcasts from the Desktop Agent. Provided for backwards compatibility with versions FDC3 standard <2.0. **See also:** @@ -747,10 +1257,23 @@ Adds a listener for incoming context broadcasts from the Desktop Agent. Provided ### `getSystemChannels` (deprecated) + + + ```ts getSystemChannels() : Promise>; ``` + + + +```csharp +TBC +``` + + + + Alias to the [`getUserChannels`](#getuserchannels) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard. **See also:** @@ -758,10 +1281,23 @@ Alias to the [`getUserChannels`](#getuserchannels) function provided for backwar ### `joinChannel` (deprecated) + + + ```ts joinChannel(channelId: string) : Promise; ``` + + + +```csharp +TBC +``` + + + + Alias to the [`joinUserChannel`](#joinuserchannel) function provided for backwards compatibility with version 1.1 & 1.2 of the FDC3 standard. **See also:** @@ -770,10 +1306,23 @@ Alias to the [`joinUserChannel`](#joinuserchannel) function provided for backwar ### `open` (deprecated) + + + ```ts open(name: string, context?: Context): Promise; ``` + + + +```csharp +TBC +``` + + + + Version of `open` that launches an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard <2.0. **See also:** @@ -782,10 +1331,23 @@ Version of `open` that launches an app by name rather than `AppIdentifier`. Prov ### `raiseIntent` (deprecated) + + + ```ts raiseIntent(intent: string, context: Context, name: string): Promise; ``` + + + +```csharp +TBC +``` + + + + Version of `raiseIntent` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard <2.0. **See also:** @@ -794,10 +1356,23 @@ Version of `raiseIntent` that targets an app by name rather than `AppIdentifier` ### `raiseIntentForContext` (deprecated) + + + ```ts raiseIntentForContext(context: Context, name: string): Promise;; ``` + + + +```csharp +TBC +``` + + + + Version of `raiseIntentForContext` that targets an app by name rather than `AppIdentifier`. Provided for backwards compatibility with versions of the FDC3 Standard <2.0. **See also:** diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index b5a9144f7..561afca50 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -2,11 +2,17 @@ title: Errors --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + FDC3 API operations may sometimes result in an error, which must be returned to the caller. Errors should be returned by rejecting the promise returned by the API with a JavaScript `Error` object (or equivalent for the language of the implementation). The `Error` Object's message should be chosen from the appropriate Error enumeration below. ## `ChannelError` -```typescript + + + +```ts enum ChannelError { /** Returned if the specified channel is not found when attempting to join a * channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`). @@ -32,6 +38,16 @@ enum ChannelError { } ``` + + + +```csharp +TBC +``` + + + + Contains constants representing the errors that can be encountered when calling channels using the [`joinUserChannel`](DesktopAgent#joinuserchannel) or [`getOrCreateChannel`](DesktopAgent#getorcreatechannel) methods, or the [`getCurrentContext`](Channel#getcurrentcontext), [`broadcast`](Channel#broadcast) or [`addContextListener`](Channel#addcontextlistener) methods on the `Channel` object. **See also:** @@ -45,7 +61,10 @@ Contains constants representing the errors that can be encountered when calling ## `OpenError` -```typescript + + + +```ts enum OpenError { /** Returned if the specified application is not found.*/ AppNotFound = 'AppNotFound', @@ -75,6 +94,16 @@ enum OpenError { } ``` + + + +```csharp +TBC +``` + + + + Contains constants representing the errors that can be encountered when calling the [`open`](DesktopAgent#open) method on the [DesktopAgent](DesktopAgent) object. **See also:** @@ -83,7 +112,10 @@ Contains constants representing the errors that can be encountered when calling ## `ResolveError` -```typescript + + + +```ts export enum ResolveError { /** SHOULD be returned if no apps are available that can resolve the intent * and context combination. @@ -134,6 +166,16 @@ export enum ResolveError { } ``` + + + +```csharp +TBC +``` + + + + Contains constants representing the errors that can be encountered when calling the [`findIntent`](DesktopAgent#findintent), [`findIntentsByContext`](DesktopAgent#findintentsbycontext), [`raiseIntent`](DesktopAgent#raiseintent) or [`raiseIntentForContext`](DesktopAgent#raiseintentforcontext) methods on the [DesktopAgent](DesktopAgent). **See also:** @@ -145,7 +187,10 @@ Contains constants representing the errors that can be encountered when calling ## `ResultError` -```typescript + + + +```ts enum ResultError { /** Returned if the intent handler exited without returning a valid result * (a promise resolving to a Context, Channel object or void). @@ -159,6 +204,16 @@ enum ResultError { } ``` + + + +```csharp +TBC +``` + + + + Contains constants representing the errors that can be encountered when calling the [`getResult`](DesktopAgent#findintent) method on the [IntentResolution](Metadata#intentresolution) Object. **See also:** @@ -171,7 +226,10 @@ Contains constants representing the errors that can be encountered when calling `@experimental` -```typescript + + + +```ts enum BridgingError { /** @experimental Returned if a Desktop Agent did not return a response, via * Desktop Agent Bridging, within the alloted timeout. */ @@ -192,6 +250,16 @@ enum BridgingError { } ``` + + + +```csharp +TBC +``` + + + + Contains constants representing the errors that can be encountered when queries are forwarded to a Desktop Agent Bridge, but one or more remote Desktop Agents connected to it disconnects, times-out or a malformed message is encountered while a particular request is in flight. These errors may be returned via the FDC3 API when a Desktop Agent is (or was) connected to a Desktop Agent Bridge. **See also:** diff --git a/docs/api/ref/Globals.md b/docs/api/ref/Globals.md deleted file mode 100644 index 4e419c9af..000000000 --- a/docs/api/ref/Globals.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Globals ---- - -Since FDC3 is typically available to the whole web application, desktop agents are expected to make the [`DesktopAgent`](DesktopAgent) interface available at a global level. - -## `window.fdc3` Object - -The global `fdc3` object can be used to access FDC3 API operations, if the current desktop agent supports FDC3. - -**Example:** - -```ts -// check if fdc3 is available -if (window.fdc3) { - // raise an intent - await window.fdc3.raiseIntent('StartChat', { - type: 'fdc3.contact', - id: { email: 'johndoe@mail.com' } - }) -} -``` - -## `fdc3Ready` Event - -The global `window.fdc3` should only be available after the API is ready to use. To prevent the API from being used before it is ready, implementors should provide an `fdc3Ready` event. - -**Example:** - -```ts -function fdc3Action() { - // Make some fdc3 API calls here -} - -if (window.fdc3) { - fdc3Action(); -} else { - window.addEventListener('fdc3Ready', fdc3Action); -} -``` - -## `fdc3Ready()` Function - -If you are using the `@finos/fdc3` NPM package, it includes a handy wrapper function that will check for the existence of `window.fdc3` and wait on the `fdc3Ready` event for you. - -It returns a promise that will resolve immediately if the `window.fdc3` global is already defined, or reject with an error if the `fdc3Ready` event doesn't fire after a specified timeout period (default: 5 seconds). - -**Example:** - -```ts -import { fdc3Ready, broadcast } from '@finos/fdc3' - -async function fdc3Action() { - try { - await fdc3Ready(1000); // wait for (at most) 1 second - broadcast({ - type: 'fdc3.instrument', - id: { ticker: 'AAPL' } - }) - } catch (error) { - // handle error - } -} -``` diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index c149124e5..a38413fb0 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -2,10 +2,16 @@ title: Metadata --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + FDC3 API operations return various types of metadata. ## `AppIntent` + + + ```ts interface AppIntent { /** Details of the intent whose relationship to resolving applications is @@ -18,6 +24,16 @@ interface AppIntent { } ``` + + + +```csharp +TBC +``` + + + + An interface that represents the binding of an intent to apps, returned as part of intent discovery. For each intent, it reference the applications that support that intent. @@ -30,6 +46,9 @@ For each intent, it reference the applications that support that intent. ## `AppMetadata` + + + ```ts interface AppMetadata extends AppIdentifier { /** @@ -81,6 +100,16 @@ interface AppMetadata extends AppIdentifier { } ``` + + + +```csharp +TBC +``` + + + + Extends an AppIdentifier, describing an application or instance of an application, with additional descriptive metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to. The additional information from an app directory can aid in rendering UI elements, such as a launcher menu or resolver UI. This includes a title, description, tooltip and icon and screenshot URLs. @@ -99,6 +128,9 @@ Note that as `AppMetadata` instances are also `AppIdentifiers` they may be passe ## `ContextMetadata` + + + ```ts interface ContextMetadata { /** Identifier for the app instance that sent the context and/or intent. @@ -108,6 +140,16 @@ interface ContextMetadata { } ``` + + + +```csharp +TBC +``` + + + + Metadata relating to a context or intent & context received through the `addContextListener` and `addIntentListener` functions. Currently identifies the app that originated the context or intent message. [`@experimental`](../../fdc3-compliance#experimental-features) Introduced in FDC3 2.0 and may be refined by further changes outside the normal FDC3 versioning policy. @@ -123,6 +165,9 @@ Metadata relating to a context or intent & context received through the `addCont ## `DisplayMetadata` + + + ```ts interface DisplayMetadata { /** @@ -141,6 +186,16 @@ interface DisplayMetadata { } ``` + + + +```csharp +TBC +``` + + + + A desktop agent (typically for _system_ channels) may want to provide additional information about how a channel can be represented in a UI. A common use case is for color linking. **See also:** @@ -150,7 +205,10 @@ A desktop agent (typically for _system_ channels) may want to provide additional ## `Icon` -```typescript + + + +```ts interface Icon { src: string; size?: string; @@ -158,13 +216,26 @@ interface Icon { } ``` + + + +```csharp +TBC +``` + + + + Metadata relating to a single icon image at a remote URL, used to represent an application in a user interface. AppMetadata includes an icons property allowing multiple icon types to be specified. Various properties may be used by the Desktop Agent to decide which icon is the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system. **Example:** -```js + + + +```ts "icons": [ { "src": "https://app.foo.icon/app_icons/lowres.webp", @@ -179,6 +250,16 @@ AppMetadata includes an icons property allowing multiple icon types to be specif ] ``` + + + +```csharp +TBC +``` + + + + **Properties:** - **`src`:** The fully qualified url to the icon. @@ -191,7 +272,10 @@ AppMetadata includes an icons property allowing multiple icon types to be specif ## `Image` -```typescript + + + +```ts interface Image { src: string; size?: string; @@ -200,13 +284,26 @@ interface Image { } ``` + + + +```csharp +TBC +``` + + + + Metadata relating to a single image at a remote URL, used to represent screenshot images. AppMetadata includes a screenshots property allowing multiple images to be specified. Various properties may be used by the Desktop Agent to decide which image(s) are the most suitable to be used considering the application chooser UI, device DPI and formats supported by the system. **Example:** -```js + + + +```ts "screenshots": [ { "src": "https://app.foo.icon/app_screenshots/dashboard.png", @@ -223,6 +320,16 @@ AppMetadata includes a screenshots property allowing multiple images to be speci ] ``` + + + +```csharp +TBC +``` + + + + **Properties:** - **`src`:** The fully qualified url to the image. @@ -235,6 +342,9 @@ AppMetadata includes a screenshots property allowing multiple images to be speci ## `ImplementationMetadata` + + + ```ts interface ImplementationMetadata { /** The version number of the FDC3 specification that the implementation @@ -275,6 +385,16 @@ interface ImplementationMetadata { } ``` + + + +```csharp +TBC +``` + + + + Metadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provider, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number and the metadata of the calling application according to the desktop agent. **See also:** @@ -284,6 +404,9 @@ Metadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provid ## `IntentMetadata` + + + ```ts interface IntentMetadata { /** The unique name of the intent that can be invoked by the raiseIntent call. */ @@ -297,6 +420,16 @@ interface IntentMetadata { } ``` + + + +```csharp +TBC +``` + + + + The interface used to describe an intent within the platform. **See also:** @@ -305,6 +438,9 @@ The interface used to describe an intent within the platform. ## `IntentResolution` + + + ```ts interface IntentResolution { @@ -341,11 +477,24 @@ interface IntentResolution { } ``` + + + +```csharp +TBC +``` + + + + IntentResolution provides a standard format for data returned upon resolving an intent. **Examples:** -```js + + + +```ts // Resolve a "Chain" type intent let resolution = await agent.raiseIntent("intentName", context); @@ -357,7 +506,7 @@ try { //Some time later await agent.raiseIntent("UpdateOrder", context, resolution.source); } -catch (err) { ... } +catch (err: ResolveError) { ... } //Resolve a "Client-Service" type intent with a data or channel response let resolution = await agent.raiseIntent("intentName", context); @@ -370,11 +519,21 @@ try { } else { console.error(`${resolution.source} didn't return anything`); } -} catch(error) { +} catch(error: ResultError) { console.error(`${resolution.source} returned an error: ${error}`); } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`IntentResult`](Types#intentresult) diff --git a/docs/api/ref/PrivateChannel.md b/docs/api/ref/PrivateChannel.md index 5fc8e9c55..91c99eef3 100644 --- a/docs/api/ref/PrivateChannel.md +++ b/docs/api/ref/PrivateChannel.md @@ -4,6 +4,10 @@ sidebar_label: PrivateChannel title: PrivateChannel hide_title: true --- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # `PrivateChannel` Object representing a private context channel, which is intended to support secure communication between applications, and extends the `Channel` interface with event handlers which provide information on the connection state of both parties, ensuring that desktop agents do not need to queue or retain messages that are broadcast before a context listener is added and that applications are able to stop broadcasting messages when the other party has disconnected. @@ -14,6 +18,9 @@ It is intended that Desktop Agent implementations: - MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel. - MUST provide the `id` value for the channel as required by the `Channel` interface. + + + ```ts interface PrivateChannel extends Channel { // methods @@ -24,6 +31,15 @@ interface PrivateChannel extends Channel { } ``` + + + +```csharp +TBC +``` + + + **See also:** - [`Channel`](Channel) @@ -42,7 +58,10 @@ The Desktop Agent knows that a channel is being returned by inspecting the objec Although this interaction occurs entirely in frontend code, we refer to it as the 'server-side' interaction as it receives a request and initiates a stream of responses. -```typescript + + + +```ts fdc3.addIntentListener("QuoteStream", async (context) => { const channel: PrivateChannel = await fdc3.createPrivateChannel(); const symbol = context.id.ticker; @@ -69,13 +88,25 @@ fdc3.addIntentListener("QuoteStream", async (context) => { }); ``` + + + +```csharp +TBC +``` + + + ### 'Client-side' example The 'client' application retrieves a `Channel` by raising an intent with context and awaiting the result. It adds a `ContextListener` so that it can receive messages from it. If a `PrivateChannel` was returned this may in turn trigger a handler added on the 'server-side' with `onAddContextListener()` and start the stream. A listener may also be to clear up if the 'server-side' disconnects from the stream. Although this interaction occurs entirely in frontend code, we refer to it as the 'client-side' interaction as it requests and receives a stream of responses. -```javascript + + + +```ts try { const resolution3 = await fdc3.raiseIntent("QuoteStream", { type: "fdc3.instrument", id : { symbol: "AAPL" } }); try { @@ -96,22 +127,43 @@ try { } 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}`); } -} catch (resolverError) { +} catch (resolverError: ResolveError) { console.error(`Error: Intent was not resolved: ${resolverError}`); } ``` + + + +```csharp +TBC +``` + + + ## Methods ### `onAddContextListener` + + + ```ts onAddContextListener(handler: (contextType?: string) => void): Listener; ``` + + + +```csharp +TBC +``` + + + 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). @@ -122,10 +174,22 @@ Desktop Agents MUST call this for each invocation of addContextListener on this ### `onUnsubscribe` + + + ```ts onUnsubscribe(handler: (contextType?: string) => void): Listener; ``` + + + +```csharp +TBC +``` + + + Adds a listener that will be called whenever the remote app invokes `Listener.unsubscribe()` on a context listener that it previously added. Desktop Agents MUST call this when disconnect() is called by the other party, for each listener that they had added. @@ -136,10 +200,22 @@ Desktop Agents MUST call this when disconnect() is called by the other party, fo ### `onDisconnect` + + + ```ts onDisconnect(handler: () => void): Listener; ``` + + + +```csharp +TBC +``` + + + 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:** @@ -148,10 +224,22 @@ Adds a listener that will be called when the remote app terminates, for example ### `disconnect` + + + ```ts disconnect(): void; ``` + + + +```csharp +TBC +``` + + + 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. diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 48af5671f..a5a56bf7c 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -2,6 +2,9 @@ title: Types --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + FDC3 API operations make use of several type declarations. ## `AppIdentifier` @@ -10,6 +13,9 @@ Identifies an application, or instance of an application, and is used to target Will always include at least an `appId` property, which can be used with `fdc3.open`, `fdc3.raiseIntent` etc.. If the `instanceId` field is set then the `AppIdentifier` object represents a specific instance of the application that may be addressed using that Id. + + + ```ts interface AppIdentifier { /** The unique application identifier located within a specific application @@ -30,6 +36,16 @@ interface AppIdentifier { } ``` + + + +```csharp +TBC +``` + + + + **See also:** - [`AppMetadata`](Metadata#appmetadata) @@ -40,7 +56,10 @@ interface AppIdentifier { ## `Context` -```typescript + + + +```ts interface Context { id?: { [key: string]: string }; name?: string; @@ -48,6 +67,16 @@ interface Context { } ``` + + + +```csharp +TBC +``` + + + + The base interface that all contexts should extend: a context data object adhering to the [FDC3 Context Data specification](../../context/spec). This means that it must at least have a `type` property that indicates what type of data it represents, e.g. `'fdc3.contact'`. The `type` property of context objects is important for certain FDC3 operations, like [`Channel.getCurrentContext`](Channel#getCurrentContext) and [`DesktopAgent.addContextListener`](DesktopAgent#addContextListener), which allows you to filter contexts by their type. @@ -69,10 +98,23 @@ This means that it must at least have a `type` property that indicates what type ## `ContextHandler` -```typescript + + + +```ts type ContextHandler = (context: Context, metadata?: ContextMetadata) => void; ``` + + + +```csharp +TBC +``` + + + + Describes a callback that handles a context event. Optional metadata about the context message, including the app that originated the message, may be provided. Used when attaching listeners for context broadcasts. @@ -88,7 +130,10 @@ Optional metadata about the context message, including the app that originated t ## `DesktopAgentIdentifier` -```typescript + + + +```ts /** @experimental */ interface DesktopAgentIdentifier { /** Used in Desktop Agent Bridging to attribute or target a message to a @@ -97,6 +142,16 @@ interface DesktopAgentIdentifier { } ``` + + + +```csharp +TBC +``` + + + + (Experimental) Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no app details are available or are appropriate. **See also:** @@ -105,10 +160,23 @@ interface DesktopAgentIdentifier { ## `IntentHandler` -```typescript + + + +```ts type IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise | void; ``` + + + +```csharp +TBC +``` + + + + Describes a callback that handles a context event and may return a promise of a Context, Channel object or `void` to be returned to the application that raised the intent. Used when attaching listeners for raised intents. @@ -125,10 +193,23 @@ Optional metadata about the intent & context message, including the app that ori ## `IntentResult` -```typescript + + + +```ts type IntentResult = Context | Channel | void; ``` + + + +```csharp +TBC +``` + + + + Describes results that an Intent handler may return that should be communicated back to the app that raised the intent, via the [`IntentResolution`](Metadata#intentresolution). Represented as a union type in TypeScript, however, this type may be rendered as an interface in other languages that both the `Context` and `Channel` types implement, allowing either to be returned by an `IntentHandler`. @@ -146,18 +227,44 @@ Represented as a union type in TypeScript, however, this type may be rendered as 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. -```typescript + + + +```ts interface Listener { unsubscribe(): void; } ``` + + + +```csharp +TBC +``` + + + + ### `unsubscribe` + + + ```ts unsubscribe(): void; ``` + + + +```csharp +TBC +``` + + + + Allows an application to unsubscribe from listening to intents or context broadcasts. **See also:** diff --git a/docs/api/spec.md b/docs/api/spec.md index bafbad461..aefb76dd9 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -49,23 +49,7 @@ The FDC3 API specification consists of interfaces. It is expected that each Des Other interfaces defined in the spec are not critical to define as concrete types. Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library. -### API Access - -The FDC3 API can be made available to an application through a number of different methods. In the case of web applications, a Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means. - -The global `window.fdc3` must only be available after the API is ready to use. To enable applications to avoid using the API before it is ready, implementors MUST provide a global `fdc3Ready` event that is fired when the API is ready for use. Implementations should first check for the existence of the FDC3 API and add a listener for this event if it is not found: - -```js -function fdc3Stuff() { - // Make fdc3 API calls here -} - -if (window.fdc3) { - fdc3Stuff(); -} else { - window.addEventListener('fdc3Ready', fdc3Stuff); -} -``` +For implementation details relating to particular languages, and how to access the API in those languages, please see [Supported Platforms](supported-platforms). ### Standards vs. Implementation diff --git a/docs/supported-platforms.md b/docs/api/supported-platforms.md similarity index 78% rename from docs/supported-platforms.md rename to docs/api/supported-platforms.md index eb12eda4f..b5b0454c4 100644 --- a/docs/supported-platforms.md +++ b/docs/api/supported-platforms.md @@ -11,6 +11,28 @@ There are two main categories of platform: web and native, both of which are des For a web application to be FDC3-enabled, it needs to run in the context of an environment or **_Platform Provider_** that makes the FDC3 API available to the application. This environment could be a browser extension, a web or native app, or a fully-fledged desktop container framework. +### API Access & Globals + +The FDC3 API can be made available to an application through a number of different methods. In the case of web applications, a Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means. + +The global `window.fdc3` must only be available after the API is ready to use. To enable applications to avoid using the API before it is ready, implementors MUST provide a global `fdc3Ready` event that is fired when the API is ready for use. Implementations should first check for the existence of the FDC3 API and add a listener for this event if it is not found: + +```ts +function fdc3Action() { + // Make some fdc3 API calls here +} + +if (window.fdc3) { + fdc3Action(); +} else { + window.addEventListener('fdc3Ready', fdc3Action); +} +``` + +Since FDC3 is typically available to the whole web application, Desktop Agents are expected to make the [`DesktopAgent`](DesktopAgent) interface available at a global level. + +The global `window.fdc3` should only be available after the API is ready to use. To prevent the API from being used before it is ready, implementors should provide an `fdc3Ready` event. + ### Usage There are two main ways FDC3 can be used from web applications: @@ -19,7 +41,7 @@ There are two main ways FDC3 can be used from web applications: Simply rely on the global object being made available by your desktop agent, and address the API directly: -```javascript +```js function sendData() { window.fdc3.broadcast({ type: 'fdc3.instrument', @@ -88,10 +110,6 @@ const listener = await addIntentListener('ViewAnalysis', instrument => { }); ``` -**See also:** - -- [`fdc3Ready() Function`](api/ref/Globals#fdc3ready-function) - ## Native The FDC3 Standard does not currently define wire formats for an app to communicate with a Desktop Agent, nor does it define language specific API bindings, other than JavaScript and TypeScript. Hence, for a native application to be FDC3-enabled, it needs to either: diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 03e166ddc..53d9bf301 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -132,7 +132,7 @@ module.exports={ }, { "label": "Supported Platforms", - "to": "docs/supported-platforms" + "to": "docs/api/supported-platforms" }, { "label": "API Reference", diff --git a/website/sidebars.json b/website/sidebars.json index 60904acb9..efc3ede23 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -10,16 +10,15 @@ "fdc3-compliance", "fdc3-glossary", "references", - "supported-platforms", { "type": "category", "label": "API Part", "items": [ "api/spec", + "api/supported-platforms", "api/ref/DesktopAgent", "api/ref/Channel", "api/ref/PrivateChannel", - "api/ref/Globals", "api/ref/Types", "api/ref/Metadata", "api/ref/Errors" From d011cf6d674f125dec0bbe58fd4f82e64feecbe9 Mon Sep 17 00:00:00 2001 From: Kris West Date: Wed, 15 Nov 2023 18:14:05 +0000 Subject: [PATCH 02/21] Adding .NET tabs to API spec page --- docs/api/spec.md | 170 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 158 insertions(+), 12 deletions(-) diff --git a/docs/api/spec.md b/docs/api/spec.md index aefb76dd9..d7557ff25 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -4,6 +4,9 @@ sidebar_label: Overview title: API Overview (next) --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + The role of FDC3 API is to establish a baseline interface for interoperability between applications. Because FDC3 is largely an agreement between existing platforms and applications, standards should be optimized for ease of adoption rather than functional completeness. Functionality absent from a FDC3 specification is in no way a commentary on its importance. The following sections examine the API's use-cases and core concepts. The APIs a fully defined in both subsequent pages of this Part and a full set of TypeScript definitions in the [src](https://github.com/finos/FDC3/tree/master/src/api) directory of the [FDC3 GitHub repository](https://github.com/finos/FDC3/). @@ -166,7 +169,10 @@ An application may wish to retrieve information about the version of the FDC3 St Since version 1.2 of the FDC3 Standard it may do so via the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function. The metadata returned can be used, for example, to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.: -```js + + + +```ts import {compareVersionNumbers, versionIsAtLeast} from '@finos/fdc3'; if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) { @@ -176,14 +182,37 @@ if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) { } ``` + + + +```csharp +TBC +``` + + + + The [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.: -```js + + + +```ts let implementationMetadata = await fdc3.getInfo(); let {appId, instanceId} = implementationMetadata.appMetadata; ``` + + + +```csharp +TBC +``` + + + + ### Reference apps or app instance(s) and retrieve their metadata To construct workflows between applications, you need to be able to reference specific applications and instances of those applications. @@ -220,7 +249,10 @@ An optional result type is also supported when programmatically resolving an int Successful delivery of an intent depends first upon the Desktop Agent's ability to "resolve the intent" (i.e. map the intent to a specific App instance). Where the target application is ambiguous (because there is more than one application that could resolve the intent and context) Desktop Agents may resolve intents by any suitable methodology. A common method is to display a UI that allows the user to pick the desired App from a list of those that will accept the intent and context. Alternatively, the app issuing the intent may proactively handle resolution by calling [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentByContext`](ref/DesktopAgent#findintentbycontext) and then raise the intent with a specific target application, e.g.: -```js + + + +```ts // 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 @@ -259,6 +291,16 @@ const appIntents = await fdc3.findIntentByContext(context); await fdc3.raiseIntent(appIntent[0].intent, context, appIntent[0].apps[0]); ``` + + + +```csharp +TBC +``` + + + + Result context types requested are represented by their type name. A channel may be requested by passing the string `"channel"` or a channel that returns a specific type via the syntax `"channel"`, e.g. `"channel"`. Requesting intent resolution to an app returning a channel MUST include apps that are registered as returning a channel with a specific type. ### Intent Resolution @@ -282,16 +324,32 @@ If the raising of the intent resolves (or rejects), a standard [`IntentResolutio For example, to raise a specific intent: -```js + + + +```ts try { const resolution = await fdc3.raiseIntent('StageOrder', context); } catch (err){ ... } ``` + + + +```csharp +TBC +``` + + + + or to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog: -```js + + + +```ts try { const resolution = await fdc3.raiseIntentForContext(context); if (resolution.data) { @@ -301,9 +359,22 @@ try { catch (err){ ... } ``` + + + +```csharp +TBC +``` + + + + Use metadata about the resolving app instance to target a further intent -```js + + + +```ts try { const resolution = await fdc3.raiseIntent('StageOrder', context); ... @@ -314,9 +385,22 @@ try { catch (err) { ... } ``` + + + +```csharp +TBC +``` + + + + Raise an intent and retrieve either data or a channel from the IntentResolution: -```js + + + +```ts let resolution = await agent.raiseIntent("intentName", context); try { const result = await resolution.getResult(); @@ -333,6 +417,16 @@ try { } ``` + + + +```csharp +TBC +``` + + + + ### Register an Intent Handler Applications need to let the system know the intents they can support. Typically, this SHOULD be done via registration with an [App Directory](../app-directory/spec) by providing `interop.intents.listensFor` metadata. However, Desktop Agent implementations MAY support dynamic registration of an [`IntentHandler`](ref/Types#intenthandler) by an app at runtime (for example, when they add an `IntentListener` via the API) to allow for ad-hoc registration which may be helpful at development time. Although dynamic registration is not part of this specification, a Desktop Agent agent MAY choose to support any number of registration paths. @@ -413,18 +507,44 @@ There SHOULD always be a clear UX indicator of what channel an app is joined to. To find a User channel, one calls: -```js + + + +```ts // returns an array of channels const allChannels = await fdc3.getUserChannels(); const redChannel = allChannels.find(c => c.id === 'red'); ``` + + + +```csharp +TBC +``` + + + + To join a User channel, one calls: -```js + + + +```ts fdc3.joinUserChannel(redChannel.id); ``` + + + +```csharp +TBC +``` + + + + Calling `fdc3.broadcast` will now route context to the joined channel. Channel implementations SHOULD ensure that context messages broadcast by an application on a channel are not delivered back to that same application if they are joined to the channel. @@ -439,7 +559,7 @@ Desktop Agent implementations SHOULD use the following set of channels, to enabl Future versions of the FDC3 Standard may support connections between desktop agents, where differing user channel sets may cause user experience issues. ::: -```javascript +```ts const recommendedChannels = [ { id: 'fdc3.channel.1', @@ -526,7 +646,10 @@ App Channels are topics dynamically created by applications connected via FDC3. To get (or create) a [`Channel`](ref/Channel) reference, then interact with it: -```js + + + +```ts const appChannel = await fdc3.getOrCreateChannel('my_custom_channel'); // get the current context of the channel const current = await appChannel.getCurrentContext(); @@ -536,9 +659,22 @@ await appChannel.addContextListener(null, context => {...}); await appChannel.broadcast(context); ``` + + + +```csharp +TBC +``` + + + + An app can still explicitly receive context events on any [`Channel`](ref/Channel), regardless of the channel it is currently joined to. -```js + + + +```ts // check for current fdc3 channel let joinedChannel = await fdc3.getCurrentChannel() //current channel is null, as the app is not currently joined to a channel @@ -555,6 +691,16 @@ joinedChannel = await fdc3.getCurrentChannel() //current channel is now the 'blue' channel ``` + + + +```csharp +TBC +``` + + + + if another application broadcasts to "my_custom_channel" (by retrieving it and broadcasting to it via `myChannel.broadcast()`) then the broadcast will be received by the specific listener (`myChannelListener`) but NOT by the listener for joined channels (`listener`). ### Private Channels From 045224a7ebf17a5b3fcc5667f7837b523200e550 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Thu, 16 Nov 2023 07:45:21 -0500 Subject: [PATCH 03/21] Add csharp language support to documentation theme --- website/docusaurus.config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 53d9bf301..af5452168 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -49,6 +49,9 @@ module.exports={ themes: ['@docusaurus/theme-mermaid'], "plugins": [], "themeConfig": { + "prism": { + "additionalLanguages": ["csharp"] + }, "navbar": { "title": "FDC3", "logo": { From 18eaf13db4a09934985a1e00afb4d5dfb7a4c9d6 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Tue, 28 Nov 2023 06:25:16 -0500 Subject: [PATCH 04/21] Add C# usage docs for DesktopAgent --- docs/api/ref/DesktopAgent.md | 376 +++++++++++++++++++++++------------ 1 file changed, 252 insertions(+), 124 deletions(-) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 4f660deb5..38f11a24b 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -16,7 +16,7 @@ A Desktop Agent can be connected to one or more App Directories and will use dir For details of how implementations of the `DesktopAgent` are made available to applications please see [Supported Platforms](supported-platforms). - + ```ts @@ -64,7 +64,37 @@ interface DesktopAgent { ```csharp -TBC +interface IDesktopAgent +{ + // Apps + Task Open(IAppIdentifier app, IContext? context = null); + Task> FindInstances(IAppIdentifier app); + Task GetAppMetadata(IAppIdentifier app); + + // Context + Task Broadcast(IContext context); + Task AddContextListener(string? contextType, ContextHandler handler) where T : IContext; + + // Intents + Task FindIntent(string intent, IContext? context = null, string? resultType = null); + Task> FindIntentsByContext(IContext context, string? resultType = null); + Task RaiseIntent(string intent, IContext context, IAppIdentifier? app = null); + Task RaiseIntentForContext(IContext context, IAppIdentifier? app = null); + Task AddIntentListener(string intent, IntentHandler handler) where T : IContext; + + // Channels + Task GetOrCreateChannel(string channelId); + Task CreatePrivateChannel(); + Task> GetUserChannels(); + + // OPTIONAL channel management functions + Task JoinUserChannel(string channelId); + Task GetCurrentChannel(); + Task LeaveCurrentChannel(); + + // Implementation Information + Task GetInfo(); +} ``` @@ -74,7 +104,7 @@ TBC ### `addContextListener` - + ```ts @@ -85,7 +115,7 @@ addContextListener(contextType: string | null, handler: ContextHandler): Promise ```csharp -TBC +Task AddContextListener(string? contextType, ContextHandler handler) where T : IContext; ``` @@ -101,7 +131,7 @@ Optional metadata about each context message received, including the app that or **Examples:** - + ```js @@ -122,7 +152,17 @@ const contactListener = await fdc3.addContextListener('fdc3.contact', (contact, ```csharp -TBC +// any context +var listener = await _desktopAgent.AddContextListener(null, (context, meatadata) => { ... }); + +// listener for a specific type +var listener = await _desktopAgent.AddContextListener("fdc3.contact", (contact, metadata) => { ... }); + +// listener that logs metadata for the message of a specific type +var contactListener = await _desktopAgent.AddContextListener("fdc3.contact", (contact, metadata) => { + System.Diagnostics.Debug.WriteLine($"Received context message\nContext: {contact}\nOriginating app: {metadata?.Source}"); + // do something else with the context +}); ``` @@ -136,7 +176,7 @@ TBC ### `addIntentListener` - + ```ts @@ -147,7 +187,7 @@ addIntentListener(intent: string, handler: IntentHandler): Promise; ```csharp -TBC +Task AddIntentListener(string intent, IntentHandler handler) where T : IContext; ``` @@ -169,7 +209,7 @@ Optional metadata about each intent & context message received, including the ap **Examples:** - + ```js @@ -219,7 +259,17 @@ fdc3.addIntentListener("QuoteStream", async (context) => { ```csharp -TBC +//Handle a raised intent +var listener = await _desktopAgent.AddIntentListener("StartChat", (context, metadata) => { + // start chat has been requested by another application + // return IIntentResult; +}); + +//Handle a raised intent and log the originating app metadata +var listener = await _desktopAgent.AddIntentListener("StartChat", (contact, metadata) => { + System.Diagnostics.Debug.Write($"Received intent StartChat\nContext: {contact}\nOriginating app: {metadata?.Source}"); + // return IIntentResult; +}); ``` @@ -235,7 +285,7 @@ TBC ### `broadcast` - + ```ts @@ -246,7 +296,7 @@ broadcast(context: Context): Promise; ```csharp -TBC +Task Broadcast(IContext context); ``` @@ -262,7 +312,7 @@ If an application attempts to broadcast an invalid context argument the Promise **Example:** - + ```js @@ -280,7 +330,14 @@ fdc3.broadcast(instrument); ```csharp -TBC +Instrument instrument = new Instrument( + new InstrumentID() + { + Ticker = "AAPL" + } +); + +_desktopAgent.Broadcast(instrument); ``` @@ -292,7 +349,7 @@ TBC ### `createPrivateChannel` - + ```ts @@ -303,7 +360,7 @@ createPrivateChannel(): Promise; ```csharp -TBC +Task CreatePrivateChannel(); ``` @@ -323,7 +380,7 @@ It is intended that Desktop Agent implementations: **Example:** - + ```js @@ -357,7 +414,30 @@ fdc3.addIntentListener("QuoteStream", async (context) => { ```csharp -TBC +_desktopAgent.AddIntentListener("QuoteStream", async (context, metadata) => { + var channel = await _desktopAgent.CreatePrivateChannel(); + var symbol = context?.ID?.Ticker; + + // This gets called when the remote side adds a context listener + var addContextListener = channel.OnAddContextListener((contextType) => { + // broadcast price quotes as they come in from our quote feed + _feed.OnQuote(symbol, (price) => { + channel.Broadcast(new Price(price)); + }); + }); + + // This gets called when the remote side calls Listener.unsubscribe() + var unsubscribeListener = channel.OnUnsubscribe((contextType) => { + _feed.Stop(symbol); + }); + + // This gets called if the remote side closes + var disconnectListener = channel.OnDisconnect(() => { + _feed.stop(symbol); + }); + + return channel; +}); ``` @@ -371,7 +451,7 @@ TBC ### `findInstances` - + ```ts @@ -382,7 +462,7 @@ findInstances(app: AppIdentifier): Promise>; ```csharp -TBC +Task> FindInstances(IAppIdentifier app); ``` @@ -396,7 +476,7 @@ If the request fails for another reason, the promise MUST be rejected with an `E **Example:** - + ```js @@ -411,7 +491,11 @@ let resolution = fdc3.raiseIntent("ViewInstrument", context, instances[0]); ```csharp -TBC +// Retrieve a list of instances of an application +var instances = await _desktopAgent.FindInstances(new AppIdentifier("MyAppId")); + +// Target a raised intent at a specific instance +var resolution = await _desktopAgent.RaiseIntent("ViewInstrument", context, instances.First()); ``` @@ -419,7 +503,7 @@ TBC ### `findIntent` - + ```ts @@ -430,7 +514,7 @@ findIntent(intent: string, context?: Context, resultType?: string): Promise ```csharp -TBC +Task FindIntent(string intent, IContext? context = null, string? resultType = null); ``` @@ -449,7 +533,7 @@ Result types may be a type name, the string `"channel"` (which indicates that th I know 'StartChat' exists as a concept, and want to know which apps can resolve it: - + ```js @@ -485,7 +569,10 @@ const appIntent = await fdc3.findIntent("StartChat"); ```csharp -TBC +var appIntent = await _desktopAgent.FindIntent("StartChat"); + +// raise the intent against a particular app +await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First()); ``` @@ -493,7 +580,7 @@ TBC An optional input context object and/or `resultType` argument may be specified, which the resolver MUST use to filter the returned applications such that each supports the specified input and result types. - + ```js @@ -524,7 +611,26 @@ const appIntent = await fdc3.findIntent("QuoteStream", instrument, "channel ```csharp -TBC +var appIntent = await _desktopAgent.FindIntent("StartChat", contact); +// returns only apps that support the type of the specified input context: +// { +// Intent: { Name: "StartChat" }, +// Apps: { Name: "Symphony" }] +// } + +var appIntent = await _desktopAgent.FindIntent("ViewContact", "fdc3.ContactList"); +// returns only apps that return the specified result type: +// { +// Intent: { Name: "ViewContact" }, +// Apps: { AppId: "MyCRM", ResultType: "fdc3.ContactList"}] +// } + +var appIntent = await _desktopAgent.fFindIntent("QuoteStream", instrument, "channel"); +// returns only apps that return a channel which will receive the specified input and result types: +// { +// Intent: { Name: "QuoteStream" }, +// Apps: { AppId: "MyOMS", ResultType: "channel"}] +// } ``` @@ -536,7 +642,7 @@ TBC ### `findIntentsByContext` - + ```ts @@ -547,7 +653,7 @@ findIntentsByContext(context: Context, resultType?: string): Promise ```csharp -TBC +Task> FindIntentsByContext(IContext context, string? resultType = null); ``` @@ -566,7 +672,7 @@ The optional `resultType` argument may be a type name, the string `"channel"` (w I have a context object, and I want to know what I can do with it, hence, I look for intents and apps to resolve them... - + ```js @@ -598,7 +704,7 @@ const appIntents = await fdc3.findIntentsByContext(context); ```csharp -TBC +var appIntents = await _desktopAgent.FindIntentsByContext(context); ``` @@ -606,7 +712,7 @@ TBC or I look for only intents that are resolved by apps returning a particular result type - + ```js @@ -631,7 +737,21 @@ await fdc3.raiseIntent(startChat.intent.name, context, selectedApp); ```csharp -TBC +var appIntentsForType = await _desktopAgent.FindIntentsByContext(context, "fdc3.ContactList"); +// returns for example: +// [{ +// Intent: { Name: "ViewContact" }, +// Apps: [{ AppId: "Symphony" }, { AppId: "MyCRM", ResultType: "fdc3.ContactList"}] +// }]; + +// select a particular intent to raise +var startChat = appIntentsForType.First(); + +// target a particular app or instance +var selectedApp = startChat.Apps.First(); + +// raise the intent, passing the given context, targeting the app +await _desktopAgent.RaiseIntent(startChat.Intent.Name, context, selectedApp); ``` @@ -644,7 +764,7 @@ TBC ### `getAppMetadata` - + ```ts @@ -655,7 +775,7 @@ getAppMetadata(app: AppIdentifier): Promise; ```csharp -TBC +Task GetAppMetadata(IAppIdentifier app); ``` @@ -667,7 +787,7 @@ If the app is not found, the promise MUST be rejected with an `Error` Object wit **Example:** - + ```js @@ -679,7 +799,8 @@ let appMetadata = await fdc3.getAppMetadata(appIdentifier); ```csharp -TBC +var appIdentifier = new AppIdentifier("MyAppId@my.appd.com"); +var appMetadata = await _desktopAgent.GetAppMetadata(appIdentifier); ``` @@ -692,7 +813,7 @@ TBC ### `getCurrentChannel` - + ```ts @@ -703,7 +824,7 @@ getCurrentChannel() : Promise; ```csharp -TBC +Task GetCurrentChannel(); ``` @@ -715,7 +836,7 @@ Returns `null` if the app is not joined to a channel. **Example:** - + ```js @@ -727,7 +848,8 @@ let current = await fdc3.getCurrentChannel(); ```csharp -TBC +// get the current channel membership +var current = await _desktopAgent.GetCurrentChannel(); ``` @@ -739,7 +861,7 @@ TBC ### `getInfo` - + ```ts @@ -750,7 +872,7 @@ getInfo(): Promise; ```csharp -TBC +Task GetInfo(); ``` @@ -762,7 +884,7 @@ Returns an [`ImplementationMetadata`](Metadata#implementationmetadata) object. **Example:** - + ```js @@ -779,7 +901,7 @@ if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), "1.2")) { ```csharp -TBC +var version = (await _desktopAgent.GetInfo()).Fdc3Version; ``` @@ -787,7 +909,7 @@ TBC The `ImplementationMetadata` object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.: - + ```js @@ -799,7 +921,9 @@ let {appId, instanceId} = implementationMetadata.appMetadata; ```csharp -TBC +var implementationMetadata = await _desktopAgent.GetInfo(); +var appId = implementationMetadata.AppMetadata.AppId; +var instanceId = implementationMetadata.AppMetadata.InstanceId; ``` @@ -812,7 +936,7 @@ TBC ### `getOrCreateChannel` - + ```ts @@ -823,7 +947,7 @@ getOrCreateChannel(channelId: string): Promise; ```csharp -TBC +Task GetOrCreateChannel(string channelId); ``` @@ -835,7 +959,7 @@ If the Channel cannot be created or access was denied, the returned promise MUST **Example:** - + ```ts @@ -852,7 +976,15 @@ catch (err: ChannelError) { ```csharp -TBC +try +{ + var myChannel = await _desktopAgent.GetOrCreateChannel("myChannel"); + await myChannel.AddContextListener(null, (context, metadata) => { /* do something with context */}); +} +catch (Exception ex) +{ + //app could not register the channel +} ``` @@ -864,7 +996,7 @@ TBC ### `getUserChannels` - + ```ts @@ -875,7 +1007,7 @@ getUserChannels() : Promise>; ```csharp -TBC +Task> GetUserChannels(); ``` @@ -885,7 +1017,7 @@ Retrieves a list of the User Channels available for the app to join. **Example:** - + ```js @@ -897,7 +1029,8 @@ const redChannel = userChannels.find(c => c.id === 'red'); ```csharp -TBC +var userChannels = await _desktopAgent.GetUserChannels(); +var redChannel = userChannels.First(c => c.Id == "red"); ``` @@ -909,7 +1042,7 @@ TBC ### `joinUserChannel` - + ```ts @@ -920,7 +1053,7 @@ joinUserChannel(channelId: string) : Promise; ```csharp -TBC +Task JoinUserChannel(string channelId); ``` @@ -938,7 +1071,7 @@ If an error occurs (such as the channel is unavailable or the join request is de **Example:** - + ```js @@ -955,7 +1088,13 @@ fdc3.joinUserChannel(selectedChannel.id); ```csharp -TBC +// get all user channels +var channels = await _desktopAgent.GetUserChannels(); + +// create UI to pick from the User channels + +// join the channel on selection +_desktopAgent.JoinUserChannel(selectedChannel.Id); ``` @@ -967,7 +1106,7 @@ TBC ### `leaveCurrentChannel` - + ```ts @@ -978,7 +1117,7 @@ leaveCurrentChannel() : Promise; ```csharp -TBC +Task LeaveCurrentChannel(); ``` @@ -990,7 +1129,7 @@ Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3 **Example:** - + ```js @@ -1009,7 +1148,14 @@ redChannel.addContextListener(null, channelListener); ```csharp -TBC +//desktop-agent scope context listener +var fdc3Listener = await _desktopAgent.AddContextListener(null, (context, metadata) => { }); + +await _desktopAgent.LeaveCurrentChannel(); +//the fdc3Listener will now cease receiving context + +//listening on a specific channel though, will continue to work +redChannel.AddContextListener(null, channelListener); ``` @@ -1017,7 +1163,7 @@ TBC ### `open` - + ```ts @@ -1028,7 +1174,7 @@ open(app: AppIdentifier, context?: Context): Promise; ```csharp -TBC +Task Open(IAppIdentifier app, IContext? context = null); ``` @@ -1048,7 +1194,7 @@ If an error occurs while opening the app, the promise MUST be rejected with an ` **Example:** - + ```js @@ -1064,7 +1210,12 @@ let instanceIdentifier = await fdc3.open(appIdentifier, context); ```csharp -TBC +// Open an app without context, using an AppIdentifier object to specify the target +var appIdentifier = new AppIdentifier("myApp-v1.0.1"); +var instanceIdentifier = await _desktopAgent.Open(appIdentifier); + +// Open an app with context +var instanceIdentifier = await _desktopAgent.Open(appIdentifier, context); ``` @@ -1079,7 +1230,7 @@ TBC ### `raiseIntent` - + ```ts @@ -1090,7 +1241,7 @@ raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise ```csharp -TBC +Task RaiseIntent(string intent, IContext context, IAppIdentifier? app = null); ``` @@ -1111,7 +1262,7 @@ Issuing apps may optionally wait on the promise that is returned by the `getResu **Example:** - + ```ts @@ -1150,7 +1301,22 @@ catch (error: ResultError) { ```csharp -TBC +// 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 +await _desktopAgent.RaiseIntent("StartChat", context); + +// or find apps to resolve an intent to start a chat with a given contact +var appIntent = await _desktopAgent.FindIntent("StartChat", context); + +// use the metadata of an app or app instance to describe the target app for the intent +await _desktopAgent.RaiseIntent("StartChat", context, appIntent.Apps.First()); + +//Raise an intent without a context by using the null context type +await _desktopAgent.RaiseIntent("StartChat", ContextType.Nothing); + +//Raise an intent and retrieve a result from the IntentResolution +IIntentResolution resolution = await _desktopAgent.RaiseIntent("intentName", context); ``` @@ -1168,7 +1334,7 @@ TBC ### `raiseIntentForContext` - + ```ts @@ -1179,7 +1345,7 @@ raiseIntentForContext(context: Context, app?: AppIdentifier): Promise ```csharp -TBC +Task RaiseIntentForContext(IContext context, IAppIdentifier? app = null); ``` @@ -1198,7 +1364,7 @@ If a target intent and app cannot be found with the criteria provided or the use **Example:** - + ```js @@ -1213,7 +1379,11 @@ await fdc3.raiseIntentForContext(context, targetAppIdentifier); ```csharp -TBC +// Display a resolver UI for the user to select an intent and application to resolve it +var intentResolution = await _desktopAgent.RaiseIntentForContext(context); + +// Resolve against all intents registered by a specific target app for the specified context +await _desktopAgent.RaiseIntentForContext(context, targetAppIdentifier); ``` @@ -1232,20 +1402,13 @@ TBC ### `addContextListener` (deprecated) - + ```ts addContextListener(handler: ContextHandler): Promise; ``` - - - -```csharp -TBC -``` - @@ -1257,20 +1420,13 @@ Adds a listener for incoming context broadcasts from the Desktop Agent. Provided ### `getSystemChannels` (deprecated) - + ```ts getSystemChannels() : Promise>; ``` - - - -```csharp -TBC -``` - @@ -1281,20 +1437,13 @@ Alias to the [`getUserChannels`](#getuserchannels) function provided for backwar ### `joinChannel` (deprecated) - + ```ts joinChannel(channelId: string) : Promise; ``` - - - -```csharp -TBC -``` - @@ -1306,20 +1455,13 @@ Alias to the [`joinUserChannel`](#joinuserchannel) function provided for backwar ### `open` (deprecated) - + ```ts open(name: string, context?: Context): Promise; ``` - - - -```csharp -TBC -``` - @@ -1331,20 +1473,13 @@ Version of `open` that launches an app by name rather than `AppIdentifier`. Prov ### `raiseIntent` (deprecated) - + ```ts raiseIntent(intent: string, context: Context, name: string): Promise; ``` - - - -```csharp -TBC -``` - @@ -1356,20 +1491,13 @@ Version of `raiseIntent` that targets an app by name rather than `AppIdentifier` ### `raiseIntentForContext` (deprecated) - + ```ts raiseIntentForContext(context: Context, name: string): Promise;; ``` - - - -```csharp -TBC -``` - From bbd1af5c6db784a86b5d523e9144ccc834007a98 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Tue, 28 Nov 2023 07:15:56 -0500 Subject: [PATCH 05/21] Add C# usage docs for Channel --- docs/api/ref/Channel.md | 117 +++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 32 deletions(-) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index e6c6a47d3..133b2d98a 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -22,7 +22,7 @@ There are differences in behavior when you interact with a User channel via the Channels each have a unique identifier, some display metadata and operations for broadcasting context to other applications, or receiving context from other applications. - + ```ts @@ -49,7 +49,15 @@ interface Channel { ```csharp -TBC +interface IChannel: IIntentResult +{ + string Id { get; } + ChannelType Type { get; } + IDisplayMetadata? DisplayMetadata { get; } + Task Broadcast(IContext context); + Task GetCurrentContext(string? contextType); + Task AddContextListener(string? contextType, ContextHandler handler) where T : IContext; +} ``` @@ -67,7 +75,7 @@ TBC ### `id` - + ```ts @@ -78,7 +86,7 @@ public readonly id: string; ```csharp -TBC +string Id { get; } ``` @@ -88,7 +96,7 @@ Uniquely identifies the channel. It is either assigned by the desktop agent (Use ### `type` - + ```ts @@ -99,7 +107,14 @@ public readonly type: "user" | "app" | "private"; ```csharp -TBC +ChannelType Type { get; } + +public enum ChannelType +{ + User = 1, + App = 2, + Private = 3 +} ``` @@ -109,7 +124,7 @@ Can be _user_, _app_ or _private_. ### `displayMetadata` - + ```ts @@ -120,7 +135,7 @@ public readonly displayMetadata?: DisplayMetadata; ```csharp -TBC +IDisplayMetadata? DisplayMetadata { get; } ``` @@ -136,7 +151,7 @@ DisplayMetadata can be used to provide display hints for User Channels intended ### `addContextListener` - + ```ts @@ -147,7 +162,7 @@ public addContextListener(contextType: string | null, handler: ContextHandler): ```csharp -TBC +Task AddContextListener(string? contextType, ContextHandler handler) where T : IContext; ``` @@ -163,7 +178,7 @@ Optional metadata about each context message received, including the app that or Add a listener for any context that is broadcast on the channel: - + ```ts @@ -183,7 +198,19 @@ listener.unsubscribe(); ```csharp -TBC +IChannel channel; +var listener = await channel.AddContextListener(null, (context, metadata) => { + if (context.Type == ContextTypes.Contact) + { + // handle the contact + } + else if (context.Type == ContextTypes.Instrument) { + // handle the instrument + } +}); + +// later +listener.Unsubscribe(); ``` @@ -191,7 +218,7 @@ TBC Adding listeners for specific types of context that is broadcast on the channel: - + ```ts @@ -212,7 +239,17 @@ instrumentListener.unsubscribe(); ```csharp -TBC +var contactListener = await channel.AddContextListener("fdc3.contact", (contact, metadata) => { + // handle the contact +}); + +var instrumentListener = await channel.AddContextListener("fdc3.instrument", (instrument, metadata) => { + // handle the instrument +}); + +// later +contactListener.unsubscribe(); +instrumentListener.unsubscribe(); ``` @@ -227,7 +264,7 @@ TBC ### `broadcast` - + ```ts @@ -238,7 +275,7 @@ public broadcast(context: Context): Promise; ```csharp -TBC +Task Broadcast(IContext context); ``` @@ -256,7 +293,7 @@ If an application attempts to broadcast an invalid context argument the Promise **Example:** - + ```ts @@ -278,7 +315,16 @@ try { ```csharp -TBC +var instrument = new Instrument(new InstrumentID() { Ticker = "AAPL" }); + +try +{ + channel.Broadcast(instrument); +} +catch (Exception ex) +{ + // handle error +} ``` @@ -292,7 +338,7 @@ TBC ### `getCurrentContext` - + ```ts @@ -303,7 +349,7 @@ public getCurrentContext(contextType?: string): Promise; ```csharp -TBC +Task GetCurrentContext(string? contextType); ``` @@ -321,7 +367,7 @@ If getting the current context fails, the promise will be rejected with an `Erro Without specifying a context type: - + ```ts @@ -336,7 +382,14 @@ try { ```csharp -TBC +try +{ + var context = await channel.GetCurrentContext(); +} +catch (Exception ex) +{ + // handle error +} ``` @@ -344,7 +397,7 @@ TBC Specifying a context type: - + ```ts @@ -359,7 +412,14 @@ try { ```csharp -TBC +try +{ + var context = await channel.GetCurrentContext("fdc3.contact"); +} +catch (Exception ex) +{ + // handle error +} ``` @@ -375,7 +435,7 @@ TBC ### `addContextListener` (deprecated) - + ```ts @@ -385,13 +445,6 @@ TBC public addContextListener(handler: ContextHandler): Promise; ``` - - - -```csharp -TBC -``` - From 374eece8a9f1ba2c6621d79902658e78886b4eda Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Tue, 28 Nov 2023 08:42:09 -0500 Subject: [PATCH 06/21] Add C# usage docs for PrivateChannel --- docs/api/ref/PrivateChannel.md | 89 ++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 14 deletions(-) diff --git a/docs/api/ref/PrivateChannel.md b/docs/api/ref/PrivateChannel.md index 91c99eef3..07168866d 100644 --- a/docs/api/ref/PrivateChannel.md +++ b/docs/api/ref/PrivateChannel.md @@ -18,7 +18,7 @@ It is intended that Desktop Agent implementations: - MUST prevent `PrivateChannels` from being retrieved via fdc3.getOrCreateChannel. - MUST provide the `id` value for the channel as required by the `Channel` interface. - + ```ts @@ -35,11 +35,18 @@ interface PrivateChannel extends Channel { ```csharp -TBC +interface IPrivateChannel : IChannel, IIntentResult +{ + IListener OnAddContextListener(Action handler); + IListener OnUnsubscribe(Action handler); + IListener OnDisconnect(Action handler); + void Disconnect(); +} ``` + **See also:** - [`Channel`](Channel) @@ -58,7 +65,7 @@ The Desktop Agent knows that a channel is being returned by inspecting the objec Although this interaction occurs entirely in frontend code, we refer to it as the 'server-side' interaction as it receives a request and initiates a stream of responses. - + ```ts @@ -92,18 +99,42 @@ fdc3.addIntentListener("QuoteStream", async (context) => { ```csharp -TBC +_desktopAgent.AddIntentListener("QuoteStream", async (context, metadata) => { + var channel = await _desktopAgent.CreatePrivateChannel(); + var symbol = context?.ID?.Ticker; + + // This gets called when the remote side adds a context listener + var addContextListener = channel.OnAddContextListener((contextType) => { + // broadcast price quotes as they come in from our quote feed + _feed.OnQuote(symbol, (price) => { + channel.Broadcast(new Price(price)); + }); + }); + + // This gets called when the remote side calls Listener.unsubscribe() + var unsubscribeListener = channel.OnUnsubscribe((contextType) => { + _feed.Stop(symbol); + }); + + // This gets called if the remote side closes + var disconnectListener = channel.OnDisconnect(() => { + _feed.stop(symbol); + }); + + return channel; +}); ``` + ### 'Client-side' example The 'client' application retrieves a `Channel` by raising an intent with context and awaiting the result. It adds a `ContextListener` so that it can receive messages from it. If a `PrivateChannel` was returned this may in turn trigger a handler added on the 'server-side' with `onAddContextListener()` and start the stream. A listener may also be to clear up if the 'server-side' disconnects from the stream. Although this interaction occurs entirely in frontend code, we refer to it as the 'client-side' interaction as it requests and receives a stream of responses. - + ```ts @@ -139,16 +170,46 @@ try { ```csharp -TBC +var resolution = await _desktopAgent.RaiseIntent("QuoteStream", new Instrument(new InstrumentID() { Ticker = "AAPL" })); +try +{ + var result = await resolution.GetResult(); + + //check that we got a result and that it's a channel + if (result is IChannel channel) + { + var listener = await channel.AddContextListener("price", (quote, metadata) => System.Diagnostics.Debug.WriteLine(quote)); + + //if it's a PrivateChannel + if (channel is IPrivateChannel privateChannel) + { + privateChannel.OnDisconnect(() => { + System.Diagnostics.Debug.WriteLine("Quote feed went down"); + }); + + // Sometime later... + listener.Unsubscribe(); + } + } + else + { + System.Diagnostics.Debug.WriteLine($" {resolution.Source} did not return a channel"); + } +} +catch (Exception ex) +{ + // Handle exception +} ``` + ## Methods ### `onAddContextListener` - + ```ts @@ -159,7 +220,7 @@ onAddContextListener(handler: (contextType?: string) => void): Listener; ```csharp -TBC +IListener OnAddContextListener(Action handler); ``` @@ -174,7 +235,7 @@ Desktop Agents MUST call this for each invocation of addContextListener on this ### `onUnsubscribe` - + ```ts @@ -185,7 +246,7 @@ onUnsubscribe(handler: (contextType?: string) => void): Listener; ```csharp -TBC +IListener OnUnsubscribe(Action handler); ``` @@ -200,7 +261,7 @@ Desktop Agents MUST call this when disconnect() is called by the other party, fo ### `onDisconnect` - + ```ts @@ -211,7 +272,7 @@ onDisconnect(handler: () => void): Listener; ```csharp -TBC +IListener OnDisconnect(Action handler); ``` @@ -224,7 +285,7 @@ Adds a listener that will be called when the remote app terminates, for example ### `disconnect` - + ```ts @@ -235,7 +296,7 @@ disconnect(): void; ```csharp -TBC +void Disconnect(); ``` From 4431206a4334e1d73bd6d9bcd44c35d4d35eb3e0 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:18:03 -0500 Subject: [PATCH 07/21] Add C# usage docs for Errors --- docs/api/ref/Errors.md | 147 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 131 insertions(+), 16 deletions(-) diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index 561afca50..90af81cd5 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -9,7 +9,7 @@ FDC3 API operations may sometimes result in an error, which must be returned to ## `ChannelError` - + ```ts @@ -42,7 +42,34 @@ enum ChannelError { ```csharp -TBC +public static class ChannelError +{ + /// + /// Returned if the specified channel is not found when attempting to join a + /// channel via the `JoinUserChannel` function of the DesktopAgent. + /// + public static readonly string NoChannelFound = nameof(NoChannelFound); + + /// + /// SHOULD be returned when a request to join a user channel or to a retrieve + /// a Channel object via the `JoinUserChannel` or `GetOrCreateChannel` methods + /// of the DesktopAgent is denied. + /// + public static readonly string AccessDenied = nameof(AccessDenied); + + /// + /// SHOULD be returned when a channel cannot be created or retrieved via the + /// `GetOrCreateChannel` method of the DesktopAgent. + /// + public static readonly string CreationFailed = nameof(CreationFailed); + + /// + /// Returned if a call to the `Broadcast` functions is made with an invalid + /// context argument.Contexts should be Objects with at least a `Type` field + /// that has a `String` value. + /// + public static readonly string MalformedContext = nameof(MalformedContext); +} ``` @@ -61,7 +88,7 @@ Contains constants representing the errors that can be encountered when calling ## `OpenError` - + ```ts @@ -98,7 +125,37 @@ enum OpenError { ```csharp -TBC +public static class OpenError +{ + /// + /// Returned if the specified application is not found. + /// + public static readonly string AppNotFound = nameof(AppNotFound); + + /// + /// Returned if the specified application fails to launch correctly. + /// + public static readonly string ErrorOnLaunch = nameof(ErrorOnLaunch); + + /// + /// Returned if the specified application launches but fails to add a context + /// listener in order to receive the context passed to the `Open` call. + /// + public static readonly string AppTimeout = nameof(AppTimeout); + + /// + /// Returned if the FDC3 desktop agent implementation is not currently able + /// to handle the request. + /// + public static readonly string ResolverUnavailable = nameof(ResolverUnavailable); + + /// + /// Returned if a call to the `Open` function is made with an invalid + /// context argument.Contexts should be Objects with at least a `Type` field + /// that has a `String` value. + /// + public static readonly string MalformedContext = nameof(MalformedContext); +} ``` @@ -112,7 +169,7 @@ Contains constants representing the errors that can be encountered when calling ## `ResolveError` - + ```ts @@ -170,7 +227,59 @@ export enum ResolveError { ```csharp -TBC +public static class ResolveError +{ + /// + /// SHOULD be returned if no apps are available that can resolve the intent + /// and context combination. + /// + public static readonly string NoAppsFound = nameof(NoAppsFound); + + /// + /// Returned if the FDC3 desktop agent implementation is not currently able + /// to handle the request. + /// + public static readonly string ResolverUnavailable = nameof(ResolverUnavailable); + + /// + /// SHOULD be returned if a timeout cancels an intent resolution that + /// required user interaction. Please use `ResolverUnavailable` instead for + /// situations where a resolver UI or similar fails. + /// + public static readonly string ResolverTimeout = nameof(ResolverTimeout); + + /// + /// Returned if the user cancelled the resolution request, for example by + /// closing or cancelling a resolver UI. + /// + public static readonly string UserCancelledResolution = nameof(UserCancelledResolution); + + /// + /// Returned if a specified target application is not available or a new + /// instance of it cannot be opened. + /// + public static readonly string TargetAppUnavailable = nameof(TargetAppUnavailable); + + /// + /// Returned if a specified target application instance is not available, + /// for example because it has been closed. + /// + public static readonly string TargetInstanceUnavailable = nameof(TargetInstanceUnavailable); + + /// + /// Returned if the intent and context could not be delivered to the selected + /// application or instance, for example because it has not added an intent + /// handler within a timeout. + /// + public static readonly string IntentDeliveryFailed = nameof(IntentDeliveryFailed); + + /// + /// Returned if a call to one of the `RaiseIntent` functions is made with an + /// invalid context argument. Contexts should be Objects with at least a `Type` + /// field that has a `String` value. + /// + public static readonly string MalformedContext = nameof(MalformedContext); +} ``` @@ -187,7 +296,7 @@ Contains constants representing the errors that can be encountered when calling ## `ResultError` - + ```ts @@ -208,7 +317,20 @@ enum ResultError { ```csharp -TBC +public static class ResultError +{ + /// + /// Returned if the intent handler exited without returning a valid result + /// (a Task resolving to a Context, Channel object or void). + /// + public static readonly string NoResultReturned = nameof(NoResultReturned); + + /// + /// Returned if the `IntentHandler` function processing the raised intent + /// throws an error. + /// + public static readonly string IntentHandlerRejected = nameof(IntentHandlerRejected); +} ``` @@ -226,7 +348,7 @@ Contains constants representing the errors that can be encountered when calling `@experimental` - + ```ts @@ -250,13 +372,6 @@ enum BridgingError { } ``` - - - -```csharp -TBC -``` - From 9e314fd1c4855e3ed56f66714430f8a1c767b6f7 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:10:51 -0500 Subject: [PATCH 08/21] Add C# usage docs for Types --- docs/api/ref/Types.md | 68 +++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index a5a56bf7c..72e492a99 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -13,7 +13,7 @@ Identifies an application, or instance of an application, and is used to target Will always include at least an `appId` property, which can be used with `fdc3.open`, `fdc3.raiseIntent` etc.. If the `instanceId` field is set then the `AppIdentifier` object represents a specific instance of the application that may be addressed using that Id. - + ```ts @@ -40,7 +40,18 @@ interface AppIdentifier { ```csharp -TBC +interface IAppIdentifier +{ + /// + /// The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root'. + /// + string AppId { get; } + + /// + /// An optional instance identifier, indicating that this object represents a specific instance of the application described. + /// + string? InstanceId { get; } +} ``` @@ -56,7 +67,7 @@ TBC ## `Context` - + ```ts @@ -71,7 +82,24 @@ interface Context { ```csharp -TBC +interface IContext: IIntentResult, IDynamicContext where T : class +{ + T? ID { get; } + string? Name { get; } + string Type { get; } +} + +interface IContext : IContext +{ +} + +interface IDynamicContext +{ + /// + /// Underlying message as a dynamic type for accessing all properties without deserialization + /// + dynamic? Native { get; set; } +} ``` @@ -98,7 +126,7 @@ This means that it must at least have a `type` property that indicates what type ## `ContextHandler` - + ```ts @@ -109,7 +137,7 @@ type ContextHandler = (context: Context, metadata?: ContextMetadata) => void; ```csharp -TBC +delegate void ContextHandler(T context, IContextMetadata? metadata = null) where T : IContext; ``` @@ -130,7 +158,7 @@ Optional metadata about the context message, including the app that originated t ## `DesktopAgentIdentifier` - + ```ts @@ -142,13 +170,6 @@ interface DesktopAgentIdentifier { } ``` - - - -```csharp -TBC -``` - @@ -160,7 +181,7 @@ TBC ## `IntentHandler` - + ```ts @@ -171,7 +192,7 @@ type IntentHandler = (context: Context, metadata?: ContextMetadata) => Promise ```csharp -TBC +delegate Task IntentHandler(T context, IContextMetadata? metadata = null) where T : IContext; ``` @@ -193,7 +214,7 @@ Optional metadata about the intent & context message, including the app that ori ## `IntentResult` - + ```ts @@ -204,7 +225,7 @@ type IntentResult = Context | Channel | void; ```csharp -TBC +interface IIntentResult { /* Marker interface implemented by IContext and Channel */ } ``` @@ -227,7 +248,7 @@ Represented as a union type in TypeScript, however, this type may be rendered as 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. - + ```ts @@ -240,7 +261,10 @@ interface Listener { ```csharp -TBC +interface IListener +{ + void Unsubscribe(); +} ``` @@ -248,7 +272,7 @@ TBC ### `unsubscribe` - + ```ts @@ -259,7 +283,7 @@ unsubscribe(): void; ```csharp -TBC +void Unsubscribe(); ``` From 642980c7c043709f43f2292dfa899d1752b6c2e3 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:53:19 -0500 Subject: [PATCH 09/21] Add c# usage docs for Metadata --- docs/api/ref/Metadata.md | 266 +++++++++++++++++++++++++++++++++++---- 1 file changed, 242 insertions(+), 24 deletions(-) diff --git a/docs/api/ref/Metadata.md b/docs/api/ref/Metadata.md index a38413fb0..62d7c039a 100644 --- a/docs/api/ref/Metadata.md +++ b/docs/api/ref/Metadata.md @@ -9,7 +9,7 @@ FDC3 API operations return various types of metadata. ## `AppIntent` - + ```ts @@ -28,7 +28,19 @@ interface AppIntent { ```csharp -TBC +interface IAppIntent +{ + /// + /// Details of the intent whose relationship to resolving application is + /// being described. + /// + IIntentMetadata Intent { get; } + + /// + /// Details of applications that can resolve the intent. + /// + IEnumerable Apps { get; } +} ``` @@ -46,7 +58,7 @@ For each intent, it reference the applications that support that intent. ## `AppMetadata` - + ```ts @@ -104,7 +116,49 @@ interface AppMetadata extends AppIdentifier { ```csharp -TBC +interface IAppMetadata : IAppIdentifier +{ + /// + /// The unique app name that can be used with the open and raiseIntent calls. + /// + string? Name { get; } + + /// + /// The Version of the application. + /// + string? Version { get; } + + /// + /// A more user-friendly application title that can be used to render UI elements. + /// + string? Title { get; } + + /// + /// A tooltip for the application that can be used to render UI elements. + /// + string? Tooltip { get; } + + /// + /// A longer, multi-paragraph description for the application that could include markup. + /// + string? Description { get; } + + /// + /// A list of icon URLs for the application that can be used to render UI elements. + /// + IEnumerable Icons { get; } + + /// + /// A list of image URLs for the application that can be used to render UI elements. + /// + IEnumerable Screenshots { get; } + + /// + /// The type of output returned for any intent specified during resolution. May express a particular context type, + /// channel, or channel with specified type + /// + string? ResultType { get; } +} ``` @@ -128,7 +182,7 @@ Note that as `AppMetadata` instances are also `AppIdentifiers` they may be passe ## `ContextMetadata` - + ```ts @@ -144,7 +198,13 @@ interface ContextMetadata { ```csharp -TBC +interface IContextMetadata +{ + /// + /// Identifier for the app instance that sent the context and/or intent. + /// + IAppIdentifier? Source { get; } +} ``` @@ -165,7 +225,7 @@ Metadata relating to a context or intent & context received through the `addCont ## `DisplayMetadata` - + ```ts @@ -190,7 +250,24 @@ interface DisplayMetadata { ```csharp -TBC +interface IDisplayMetadata +{ + /// + /// A user-readable name for this channel, e.g: Red. + /// + string? Name { get; } + + /// + /// The color that should be associated within this channel when displaying this + /// channein in a UI, e.g: '0xFF0000'. + /// + string? Color { get; } + + /// + /// A URL of an image that can be used to display this channel. + /// + string? Glyph { get; } +} ``` @@ -205,7 +282,7 @@ A desktop agent (typically for _system_ channels) may want to provide additional ## `Icon` - + ```ts @@ -220,7 +297,23 @@ interface Icon { ```csharp -TBC +interface IIcon +{ + /// + /// The icon url + /// + string Src { get; } + + /// + /// The icon dimensions, formatted as '{height}x{width}' + /// + string? Size { get; } + + /// + /// Icon media type. If not present, the Desktop Agent may use the src file extension. + /// + string? Type { get; } +} ``` @@ -232,7 +325,7 @@ AppMetadata includes an icons property allowing multiple icon types to be specif **Example:** - + ```ts @@ -254,7 +347,7 @@ AppMetadata includes an icons property allowing multiple icon types to be specif ```csharp -TBC +IIcon? icon = appMetadata?.Icons.Where(icon => icon.Size == "48x48").First(); ``` @@ -272,7 +365,7 @@ TBC ## `Image` - + ```ts @@ -288,7 +381,29 @@ interface Image { ```csharp -TBC +interface IImage +{ + /// + /// The icon url + /// + string Src { get; } + + /// + /// The icon dimensions, formatted as '{height}x{width}' + /// + string? Size { get; } + + /// + /// Icon media type. If not present, the Desktop Agent may use the src file extension. + /// + string? Type { get; } + + + /// + /// Caption for the image + /// + string? Label { get; } +} ``` @@ -300,7 +415,7 @@ AppMetadata includes a screenshots property allowing multiple images to be speci **Example:** - + ```ts @@ -324,7 +439,10 @@ AppMetadata includes a screenshots property allowing multiple images to be speci ```csharp -TBC +foreach (IImage image in appMetadata.Screenshots) +{ + System.Diagnostics.Debug.WriteLine(image.Src); +} ``` @@ -342,7 +460,7 @@ TBC ## `ImplementationMetadata` - + ```ts @@ -389,7 +507,49 @@ interface ImplementationMetadata { ```csharp -TBC +interface IImplementationMetadata +{ + /// + /// The version number of the FDC3 specification that the implementation provides. + /// The string must be a numeric semver version, e.g. 1.2 or 1.2.1. + /// + string Fdc3Version { get; } + + /// + /// The name of the provider of the FDC3 Desktop Agent Implementation (e.g. Finsemble, Glue42, OpenFin etc.). + /// + string Provider { get; } + + /// + /// The version of the provider of the FDC3 Desktop Agent Implementation (e.g. 5.3.0). + /// + string ProviderVersion { get; } + + /// + /// Metadata indicating whether the Desktop Agent implements optional features of the Desktop Agent API. + /// + OptionalDesktopAgentFeatures OptionalFeatures { get; } + + /// + /// The calling application instance's own metadata according to the Desktop Agent + /// + IAppMetadata AppMetadata { get; } +} + +class OptionalDesktopAgentFeatures +{ + /// + /// Used to indicate whether the exposure of 'originating app metadata' for context and intent + /// messages is supported by the Desktop Agent. + /// + public bool OriginatingAppMetadata { get; set; } + + /// + /// Used to indicate whether the optional 'JoinUserChannel', 'GetCurrentChannel', and 'LeaveCurrentChannel' + /// are implemented by the Desktop Agent. + /// + public bool UserChannelMembershipAPIs { get; set; } +} ``` @@ -404,7 +564,7 @@ Metadata relating to the FDC3 [DesktopAgent](DesktopAgent) object and its provid ## `IntentMetadata` - + ```ts @@ -424,7 +584,18 @@ interface IntentMetadata { ```csharp -TBC +interface IIntentMetadata +{ + /// + /// The unique name of the intent that can be invoked by the raiseIntent call. + /// + string Name { get; } + + /// + /// A friendly display name for the intent that should be used to render UI elements. + /// + string DisplayName { get; } +} ``` @@ -438,7 +609,7 @@ The interface used to describe an intent within the platform. ## `IntentResolution` - + ```ts @@ -481,7 +652,25 @@ interface IntentResolution { ```csharp -TBC +interface IIntentResolution +{ + /// + /// The application that resolved the intent. + /// + IAppIdentifier Source { get; } + + /// + /// The intent that was raised. + /// + string Intent { get; } + + /// + /// The version number of the Intents schema being used. + /// + string? Version { get; } + + Task GetResult(); +} ``` @@ -491,7 +680,7 @@ IntentResolution provides a standard format for data returned upon resolving an **Examples:** - + ```ts @@ -528,7 +717,36 @@ try { ```csharp -TBC +var resolution = await _desktopAgent.RaiseIntent("QuoteStream", new Instrument(new InstrumentID() { Ticker = "AAPL" })); +try +{ + var result = await resolution.GetResult(); + + //check that we got a result and that it's a channel + if (result is IChannel channel) + { + var listener = await channel.AddContextListener("price", (quote, metadata) => System.Diagnostics.Debug.WriteLine(quote)); + + //if it's a PrivateChannel + if (channel is IPrivateChannel privateChannel) + { + privateChannel.OnDisconnect(() => { + System.Diagnostics.Debug.WriteLine("Quote feed went down"); + }); + + // Sometime later... + listener.Unsubscribe(); + } + } + else + { + System.Diagnostics.Debug.WriteLine($" {resolution.Source} did not return a channel"); + } +} +catch (Exception ex) +{ + // Handle exception +} ``` From cd4d755b7914b5b7e7d448c59cdc4b8dc8b0fcf1 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:53:45 -0500 Subject: [PATCH 10/21] Add C# usage docs for spec --- docs/api/spec.md | 147 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 125 insertions(+), 22 deletions(-) diff --git a/docs/api/spec.md b/docs/api/spec.md index d7557ff25..569f00ba5 100644 --- a/docs/api/spec.md +++ b/docs/api/spec.md @@ -169,7 +169,7 @@ An application may wish to retrieve information about the version of the FDC3 St Since version 1.2 of the FDC3 Standard it may do so via the [`fdc3.getInfo()`](ref/DesktopAgent#getinfo) function. The metadata returned can be used, for example, to vary the behavior of an application based on the version supported by the Desktop Agent, e.g.: - + ```ts @@ -186,7 +186,7 @@ if (fdc3.getInfo && versionIsAtLeast(await fdc3.getInfo(), '1.2')) { ```csharp -TBC +var version = (await _desktopAgent.GetInfo()).Fdc3Version; ``` @@ -194,7 +194,7 @@ TBC The [`ImplementationMetadata`](ref/Metadata#implementationmetadata) object returned also includes the metadata for the calling application, according to the Desktop Agent. This allows the application to retrieve its own `appId`, `instanceId` and other details, e.g.: - + ```ts @@ -207,7 +207,9 @@ let {appId, instanceId} = implementationMetadata.appMetadata; ```csharp -TBC +var implementationMetadata = await _desktopAgent.GetInfo(); +var appId = implementationMetadata.AppMetadata.AppId; +var instanceId = implementationMetadata.AppMetadata.InstanceId; ``` @@ -249,7 +251,7 @@ An optional result type is also supported when programmatically resolving an int Successful delivery of an intent depends first upon the Desktop Agent's ability to "resolve the intent" (i.e. map the intent to a specific App instance). Where the target application is ambiguous (because there is more than one application that could resolve the intent and context) Desktop Agents may resolve intents by any suitable methodology. A common method is to display a UI that allows the user to pick the desired App from a list of those that will accept the intent and context. Alternatively, the app issuing the intent may proactively handle resolution by calling [`findIntent`](ref/DesktopAgent#findintent) or [`findIntentByContext`](ref/DesktopAgent#findintentbycontext) and then raise the intent with a specific target application, e.g.: - + ```ts @@ -295,7 +297,48 @@ await fdc3.raiseIntent(appIntent[0].intent, context, appIntent[0].apps[0]); ```csharp -TBC +// Find apps to resolve an intent to start a chat with a given contact +var appIntent = await _desktopAgent.FindIntent("StartChat", context); +// use the returned AppIntent object to target one of the returned +// chat apps or app instances using the AppMetadata object +await _desktopAgent.RaiseIntent("StartChat", context, appIntent.Apps.First()); + +//Find apps to resolve an intent and return a specified context type +var appIntent = await _desktopAgent.FindIntent("ViewContact", context, "fdc3.contact"); +var resolution = await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First()); +try +{ + var result = await resolution.GetResult(); + System.Diagnostics.Debug.WriteLine($"{resolution.Source} returned ${result}"); +} +catch (Exception ex) +{ + System.Diagnostics.Debug.WriteLine($"{resolution.Source} returned an error"); +} + +//Find apps to resolve an intent and return a channel +var appIntent = await _desktopAgent.FindIntent("QuoteStream", context, "channel"); +try +{ + var resolution = await _desktopAgent.RaiseIntent(appIntent.Intent.Name, context, appIntent.Apps.First()); + var result = await resolution.GetResult(); + if (result is IChannel resolvedChannel) + { + await resolvedChannel.AddContextListener(null, (context, metadata) => { }); + } + else + { + System.Diagnostics.Debug.WriteLine("Did not return a channel"); + } +} +catch (Exception ex) +{ +} + +//Find apps that can perform any intent with the specified context +var appIntents = await _desktopAgent.FindIntentsByContext(context); +//use the returned AppIntent array to target one of the returned apps +await _desktopAgent.RaiseIntent(appIntents.First().Intent.Name, context, appIntents.First().Apps.First()); ``` @@ -324,7 +367,7 @@ If the raising of the intent resolves (or rejects), a standard [`IntentResolutio For example, to raise a specific intent: - + ```ts @@ -338,7 +381,11 @@ catch (err){ ... } ```csharp -TBC +try +{ + var resolution = await _desktopAgent.RaiseIntent("StageOrder", context); +} +catch (Exception ex) { } ``` @@ -346,7 +393,7 @@ TBC or to raise an unspecified intent for a specific context, where the user may select an intent from a resolver dialog: - + ```ts @@ -363,7 +410,15 @@ catch (err){ ... } ```csharp -TBC +try +{ + var resolution = await _desktopAgent.RaiseIntentForContext(context); + if (resolution is IContext resolvedContext) + { + var orderId = resolvedContext.ID; + } +} +catch (Exception ex) { } ``` @@ -371,7 +426,7 @@ TBC Use metadata about the resolving app instance to target a further intent - + ```ts @@ -389,7 +444,14 @@ catch (err) { ... } ```csharp -TBC +try +{ + var resolution = await _desktopAgent.RaiseIntent("StageOrder", context); + + //some time later + await _desktopAgent.RaiseIntent("UpdateOrder", context, resolution.Source); +} +catch (Exception ex) { } ``` @@ -397,7 +459,7 @@ TBC Raise an intent and retrieve either data or a channel from the IntentResolution: - + ```ts @@ -421,7 +483,29 @@ try { ```csharp -TBC +var resolution = await _desktopAgent.RaiseIntent("QuoteStream", new Instrument(new InstrumentID() { Ticker = "AAPL" })); +try +{ + var result = await resolution.GetResult(); + + //check that we got a result and that it's a channel + if (result is IChannel channel) + { + System.Diagnostics.Debug.WriteLine($"{resolution.Source} returned a channel with id {channel.Id}"); + } + else if (result is IContext context) + { + System.Diagnostics.Debug.WriteLine($"{resolution.Source} returned data {context}"); + } + else + { + System.Diagnostics.Debug.WriteLine($"{resolution.Source} didn't return anything"); + } +} +catch (Exception ex) +{ + System.Diagnostics.Debug.WriteLine($"{resolution.Source} returned an error"); +} ``` @@ -507,7 +591,7 @@ There SHOULD always be a clear UX indicator of what channel an app is joined to. To find a User channel, one calls: - + ```ts @@ -520,7 +604,8 @@ const redChannel = allChannels.find(c => c.id === 'red'); ```csharp -TBC +var allChannels = await _desktopAgent.GetUserChannels(); +var redChannel = allChannels.Single(c => c.Id == "red"); ``` @@ -528,7 +613,7 @@ TBC To join a User channel, one calls: - + ```ts @@ -539,7 +624,7 @@ fdc3.joinUserChannel(redChannel.id); ```csharp -TBC +await _desktopAgent.JoinUserChannel(redChannel.Id); ``` @@ -646,7 +731,7 @@ App Channels are topics dynamically created by applications connected via FDC3. To get (or create) a [`Channel`](ref/Channel) reference, then interact with it: - + ```ts @@ -663,7 +748,13 @@ await appChannel.broadcast(context); ```csharp -TBC +var appChannel = await _desktopAgent.GetOrCreateChannel("my_custom_channel"); +// get the current context of the channel +var current = await appChannel.GetCurrentContext(null); +// add a listener +await appChannel.AddContextListener(null, (context, metadata) => { }); +// broadcast to the channel +await appChannel.Broadcast(context); ``` @@ -671,7 +762,7 @@ TBC An app can still explicitly receive context events on any [`Channel`](ref/Channel), regardless of the channel it is currently joined to. - + ```ts @@ -695,7 +786,19 @@ joinedChannel = await fdc3.getCurrentChannel() ```csharp -TBC +var joinedChannel = await _desktopAgent.GetCurrentChannel(); +// current channel is null, as the app is not currently joined to a channel + +// add a context listener for channels we join +var listener = await _desktopAgent.AddContextListener(null, (context, metadata) => { }); + +// retrieve an App Channel and add a listener that is specific to that channel +var myChannel = await _desktopAgent.GetOrCreateChannel("my_custom_channel"); +var myChannelListener = await myChannel.AddContextListener(null, (context, metadata) => { }); + +await _desktopAgent.JoinUserChannel("blue"); +joinedChannel = await _desktopAgent.GetCurrentChannel(); +// current channel is now the "blue" channel ``` From eba8b0b1c60674c6e82e670048c2429b7432b8b1 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:49:57 -0400 Subject: [PATCH 11/21] Initial barebones .NET getting started --- docs/api/supported-platforms.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/api/supported-platforms.md b/docs/api/supported-platforms.md index b5b0454c4..db878ca37 100644 --- a/docs/api/supported-platforms.md +++ b/docs/api/supported-platforms.md @@ -112,10 +112,22 @@ const listener = await addIntentListener('ViewAnalysis', instrument => { ## Native +### .NET + +For a .NET application to be FDC3-enabled, it needs to run in the context of a platform provider that makes the FDC3 API available. The manner in which you get a reference to the desktop agent can be highly dependent on the provider chosen. For those looking to implement your own desktop agent, a recommended and typical design is to register an instance of the desktop agent at startup which can be injected into any class constructors that need references through inversion of control. More details for creating your own DesktopAgent can be found in the [fdc3-dotnet repository](https://github.com/finos/fdc3-dotnet). + +#### Usage + +FDC3 offers the [`Finos.Fdc3` NuGet package](https://www.nuget.org/packages/Finos.Fdc3) that can by used by .NET applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations. + + + + ## Hybrid From dccfe0fcf200ff9d2e468ac5b16fcc11eb5863e1 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:57:38 -0400 Subject: [PATCH 12/21] Remote commented out documentation placeholder --- docs/api/supported-platforms.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/api/supported-platforms.md b/docs/api/supported-platforms.md index db878ca37..0db938409 100644 --- a/docs/api/supported-platforms.md +++ b/docs/api/supported-platforms.md @@ -121,14 +121,6 @@ For a .NET application to be FDC3-enabled, it needs to run in the context of a p FDC3 offers the [`Finos.Fdc3` NuGet package](https://www.nuget.org/packages/Finos.Fdc3) that can by used by .NET applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations. - - - ## Hybrid In a hybrid application, a standalone native application incorporates a web view, within which a web application runs. This may be considered a special case of the web platform where all platform-provider requirements for web applications must be satisfied, but it is the responsibility of the associated native application, rather than a platform provider, to ensure they are fulfilled. This may be achieved, for example, by injecting an implementation of the DesktopAgent API and ensuring that it is accessible at the usual location, `window.fdc3`. From 34e6fb103c5a04b90c921cd0ca3166a6220b2370 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Fri, 12 Jul 2024 16:10:11 -0400 Subject: [PATCH 13/21] Fix spelling --- docs/api/supported-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/supported-platforms.md b/docs/api/supported-platforms.md index 0db938409..497284171 100644 --- a/docs/api/supported-platforms.md +++ b/docs/api/supported-platforms.md @@ -58,7 +58,7 @@ if (window.fdc3) { #### 2. NPM Wrapper -FDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can by used by web applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations. +FDC3 offers the [`@finos/fdc3` npm package](https://www.npmjs.com/package/@finos/fdc3) that can be used by web applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations. import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; @@ -118,7 +118,7 @@ For a .NET application to be FDC3-enabled, it needs to run in the context of a p #### Usage -FDC3 offers the [`Finos.Fdc3` NuGet package](https://www.nuget.org/packages/Finos.Fdc3) that can by used by .NET applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations. +FDC3 offers the [`Finos.Fdc3` NuGet package](https://www.nuget.org/packages/Finos.Fdc3) that can be used by .NET applications to target operations from the [API Specification](api/spec) in a consistent way. Each FDC3-compliant desktop agent that the application runs in, can then provide an implementation of the FDC3 API operations. ## Hybrid From 96c302b62caddaa2badfa972b0ef9aaf9f57a334 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Fri, 12 Jul 2024 16:31:42 -0400 Subject: [PATCH 14/21] Add lang tab for addEventListener. Omit .NET as it is not supported. --- docs/api/ref/DesktopAgent.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 89b01358d..d480a9790 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -178,16 +178,26 @@ var contactListener = await _desktopAgent.AddContextListener("fdc3.cont - [`ContextHandler`](Types#contexthandler) ### `addEventListener` + + + + ```ts addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise; ``` + + + Registers a handler for non-context and non-intent events from the Desktop Agent. If the consumer is only interested in an event of a particular type, they can specify that type. If the consumer is able to receive events of any type or will inspect types received, then they can pass `null` as the `type` parameter to receive all event types. Whenever the handler function is called it will be passed an event object with details related to the event. **Examples:** + + + ```js // any event type const listener = await fdc3.addEventListener(null, event => { ... }); @@ -197,9 +207,10 @@ const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USE console.log(`Received event ${event.type}\n\tDetails: ${event.details}`); //do something else with the event }); -```` - +``` + + ### `addIntentListener` From a5a9e94144b67770fd1e639774bef6d3c7d90153 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:46:33 -0400 Subject: [PATCH 15/21] Add tab mentioning not implemented for obsolete/experiemental members --- docs/api/ref/Channel.md | 6 ++++++ docs/api/ref/DesktopAgent.md | 40 ++++++++++++++++++++++++++++++++++++ docs/api/ref/Errors.md | 6 ++++++ docs/api/ref/Types.md | 6 ++++++ 4 files changed, 58 insertions(+) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index 133b2d98a..3d53ab3da 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -446,6 +446,12 @@ public addContextListener(handler: ContextHandler): Promise; ``` + + +Not implemented + + + Adds a listener for incoming contexts whenever a broadcast happens on the channel. diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index d480a9790..352bec94b 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -186,6 +186,11 @@ var contactListener = await _desktopAgent.AddContextListener("fdc3.cont addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise; ``` + + + +Not implemented + @@ -209,6 +214,11 @@ const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USE }); ``` + + + +Not implemented + @@ -1447,6 +1457,11 @@ await _desktopAgent.RaiseIntentForContext(context, targetAppIdentifier); addContextListener(handler: ContextHandler): Promise; ``` + + + +Not implemented + @@ -1465,6 +1480,11 @@ Adds a listener for incoming context broadcasts from the Desktop Agent. Provided getSystemChannels() : Promise>; ``` + + + +Not implemented + @@ -1482,6 +1502,11 @@ Alias to the [`getUserChannels`](#getuserchannels) function provided for backwar joinChannel(channelId: string) : Promise; ``` + + + +Not implemented + @@ -1500,6 +1525,11 @@ Alias to the [`joinUserChannel`](#joinuserchannel) function provided for backwar open(name: string, context?: Context): Promise; ``` + + + +Not implemented + @@ -1518,6 +1548,11 @@ Version of `open` that launches an app by name rather than `AppIdentifier`. Prov raiseIntent(intent: string, context: Context, name: string): Promise; ``` + + + +Not implemented + @@ -1536,6 +1571,11 @@ Version of `raiseIntent` that targets an app by name rather than `AppIdentifier` raiseIntentForContext(context: Context, name: string): Promise; ``` + + + +Not implemented + diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index 90af81cd5..b48a83809 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -373,6 +373,12 @@ enum BridgingError { ``` + + +Not implemented + + + Contains constants representing the errors that can be encountered when queries are forwarded to a Desktop Agent Bridge, but one or more remote Desktop Agents connected to it disconnects, times-out or a malformed message is encountered while a particular request is in flight. These errors may be returned via the FDC3 API when a Desktop Agent is (or was) connected to a Desktop Agent Bridge. diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 72e492a99..02195ab68 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -171,6 +171,12 @@ interface DesktopAgentIdentifier { ``` + + +Not implemented + + + (Experimental) Identifies a particular Desktop Agent in Desktop Agent Bridging scenarios where a request needs to be directed to a Desktop Agent rather than a specific app, or a response message is returned by the Desktop Agent (or more specifically its resolver) rather than a specific app. Used as a substitute for `AppIdentifier` in cases where no app details are available or are appropriate. From 092a0221d555e67dbe1366653d9d525535b2b0ae Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:54:48 -0400 Subject: [PATCH 16/21] Wrap 'Not implemented' in code block to improve readability --- docs/api/ref/Channel.md | 4 ++-- docs/api/ref/DesktopAgent.md | 32 ++++++++++++++++---------------- docs/api/ref/Errors.md | 4 ++-- docs/api/ref/Types.md | 4 ++-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index 3d53ab3da..4ff33c1a7 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -447,9 +447,9 @@ public addContextListener(handler: ContextHandler): Promise; - +``` Not implemented - +``` diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 352bec94b..280f7cd0a 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -188,9 +188,9 @@ addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise
  • - +``` Not implemented - +``` @@ -216,9 +216,9 @@ const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USE - +``` Not implemented - +``` @@ -1459,9 +1459,9 @@ addContextListener(handler: ContextHandler): Promise; - +``` Not implemented - +``` @@ -1482,9 +1482,9 @@ getSystemChannels() : Promise>; - +``` Not implemented - +``` @@ -1504,9 +1504,9 @@ joinChannel(channelId: string) : Promise; - +``` Not implemented - +``` @@ -1527,9 +1527,9 @@ open(name: string, context?: Context): Promise; - +``` Not implemented - +``` @@ -1550,9 +1550,9 @@ raiseIntent(intent: string, context: Context, name: string): Promise - +``` Not implemented - +``` @@ -1573,9 +1573,9 @@ raiseIntentForContext(context: Context, name: string): Promise - +``` Not implemented - +``` diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index b48a83809..d437c2b73 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -374,9 +374,9 @@ enum BridgingError { - +``` Not implemented - +``` diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 02195ab68..e604d74f2 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -172,9 +172,9 @@ interface DesktopAgentIdentifier { - +``` Not implemented - +``` From 6ed7da53e17c9547d8113b0561d8a24e00435af3 Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:16:03 -0400 Subject: [PATCH 17/21] Update csharp not implemented to comment style --- docs/api/ref/Channel.md | 4 ++-- docs/api/ref/DesktopAgent.md | 32 ++++++++++++++++---------------- docs/api/ref/Errors.md | 4 ++-- docs/api/ref/Types.md | 4 ++-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index 4ff33c1a7..135f5ba44 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -447,8 +447,8 @@ public addContextListener(handler: ContextHandler): Promise; -``` -Not implemented +```csharp +// Not implemented ``` diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 280f7cd0a..539194e41 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -188,8 +188,8 @@ addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise
  • -``` -Not implemented +```csharp +// Not implemented ``` @@ -216,8 +216,8 @@ const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USE -``` -Not implemented +```csharp +// Not implemented ``` @@ -1459,8 +1459,8 @@ addContextListener(handler: ContextHandler): Promise; -``` -Not implemented +```csharp +// Not implemented ``` @@ -1482,8 +1482,8 @@ getSystemChannels() : Promise>; -``` -Not implemented +```csharp +// Not implemented ``` @@ -1504,8 +1504,8 @@ joinChannel(channelId: string) : Promise; -``` -Not implemented +```csharp +// Not implemented ``` @@ -1527,8 +1527,8 @@ open(name: string, context?: Context): Promise; -``` -Not implemented +```csharp +// Not implemented ``` @@ -1550,8 +1550,8 @@ raiseIntent(intent: string, context: Context, name: string): Promise -``` -Not implemented +```csharp +// Not implemented ``` @@ -1573,8 +1573,8 @@ raiseIntentForContext(context: Context, name: string): Promise -``` -Not implemented +```csharp +// Not implemented ``` diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index d437c2b73..98ffb1d37 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -374,8 +374,8 @@ enum BridgingError { -``` -Not implemented +```csharp +// Not implemented ``` diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index e604d74f2..905c28798 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -172,8 +172,8 @@ interface DesktopAgentIdentifier { -``` -Not implemented +```csharp +// Not implemented ``` From e978f6b35ca83357c536204324d38190f11b4a1c Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:22:04 -0400 Subject: [PATCH 18/21] Add padding around csharp example --- docs/api/ref/Channel.md | 2 ++ docs/api/ref/DesktopAgent.md | 16 ++++++++++++++++ docs/api/ref/Errors.md | 2 ++ docs/api/ref/Types.md | 2 ++ 4 files changed, 22 insertions(+) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index 135f5ba44..61df5735b 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -447,9 +447,11 @@ public addContextListener(handler: ContextHandler): Promise; + ```csharp // Not implemented ``` + diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 539194e41..5621a8c8b 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -188,9 +188,11 @@ addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise
  • + ```csharp // Not implemented ``` + @@ -216,9 +218,11 @@ const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USE + ```csharp // Not implemented ``` + @@ -1459,9 +1463,11 @@ addContextListener(handler: ContextHandler): Promise; + ```csharp // Not implemented ``` + @@ -1482,9 +1488,11 @@ getSystemChannels() : Promise>; + ```csharp // Not implemented ``` + @@ -1504,9 +1512,11 @@ joinChannel(channelId: string) : Promise; + ```csharp // Not implemented ``` + @@ -1527,9 +1537,11 @@ open(name: string, context?: Context): Promise; + ```csharp // Not implemented ``` + @@ -1550,9 +1562,11 @@ raiseIntent(intent: string, context: Context, name: string): Promise + ```csharp // Not implemented ``` + @@ -1573,9 +1587,11 @@ raiseIntentForContext(context: Context, name: string): Promise + ```csharp // Not implemented ``` + diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index 98ffb1d37..f3b475b9d 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -374,9 +374,11 @@ enum BridgingError { + ```csharp // Not implemented ``` + diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 905c28798..38ea5eede 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -172,9 +172,11 @@ interface DesktopAgentIdentifier { + ```csharp // Not implemented ``` + From 6797823f1a5c6b6b546caf94aa4745bbbf8c73fb Mon Sep 17 00:00:00 2001 From: bingenito <28159742+bingenito@users.noreply.github.com> Date: Thu, 22 Aug 2024 07:57:16 -0400 Subject: [PATCH 19/21] Remove formatting --- docs/api/ref/Channel.md | 4 ++-- docs/api/ref/DesktopAgent.md | 32 ++++++++++++++++---------------- docs/api/ref/Errors.md | 4 ++-- docs/api/ref/Types.md | 4 ++-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/api/ref/Channel.md b/docs/api/ref/Channel.md index 61df5735b..4f949f09d 100644 --- a/docs/api/ref/Channel.md +++ b/docs/api/ref/Channel.md @@ -448,8 +448,8 @@ public addContextListener(handler: ContextHandler): Promise; -```csharp -// Not implemented +``` +Not implemented ``` diff --git a/docs/api/ref/DesktopAgent.md b/docs/api/ref/DesktopAgent.md index 5621a8c8b..9c452b1f2 100644 --- a/docs/api/ref/DesktopAgent.md +++ b/docs/api/ref/DesktopAgent.md @@ -189,8 +189,8 @@ addEventListener(type: FDC3EventType | null, handler: EventHandler): Promise
  • -```csharp -// Not implemented +``` +Not implemented ``` @@ -219,8 +219,8 @@ const userChannelChangedListener = await fdc3.addEventListener(FDC3EventType.USE -```csharp -// Not implemented +``` +Not implemented ``` @@ -1464,8 +1464,8 @@ addContextListener(handler: ContextHandler): Promise; -```csharp -// Not implemented +``` +Not implemented ``` @@ -1489,8 +1489,8 @@ getSystemChannels() : Promise>; -```csharp -// Not implemented +``` +Not implemented ``` @@ -1513,8 +1513,8 @@ joinChannel(channelId: string) : Promise; -```csharp -// Not implemented +``` +Not implemented ``` @@ -1538,8 +1538,8 @@ open(name: string, context?: Context): Promise; -```csharp -// Not implemented +``` +Not implemented ``` @@ -1563,8 +1563,8 @@ raiseIntent(intent: string, context: Context, name: string): Promise -```csharp -// Not implemented +``` +Not implemented ``` @@ -1588,8 +1588,8 @@ raiseIntentForContext(context: Context, name: string): Promise -```csharp -// Not implemented +``` +Not implemented ``` diff --git a/docs/api/ref/Errors.md b/docs/api/ref/Errors.md index f3b475b9d..6ce1b39ae 100644 --- a/docs/api/ref/Errors.md +++ b/docs/api/ref/Errors.md @@ -375,8 +375,8 @@ enum BridgingError { -```csharp -// Not implemented +``` +Not implemented ``` diff --git a/docs/api/ref/Types.md b/docs/api/ref/Types.md index 38ea5eede..16126d5ec 100644 --- a/docs/api/ref/Types.md +++ b/docs/api/ref/Types.md @@ -173,8 +173,8 @@ interface DesktopAgentIdentifier { -```csharp -// Not implemented +``` +Not implemented ``` From 2cde9384da3b6629593601deeda81f74e2b2c409 Mon Sep 17 00:00:00 2001 From: Kris West Date: Thu, 22 Aug 2024 14:38:32 +0100 Subject: [PATCH 20/21] Changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fec90b1f..68caa3dc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,12 @@ 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)) ### Changed +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)) From a24983cb87b73e225b9ba46bfbe49778b6fa3736 Mon Sep 17 00:00:00 2001 From: Kris West Date: Fri, 23 Aug 2024 11:55:59 +0100 Subject: [PATCH 21/21] Changelog correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68caa3dc3..e8b957c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed -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)) +* 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