Skip to content

Commit

Permalink
Private channel implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
robmoffat committed Nov 17, 2023
1 parent 684cc39 commit b497a8c
Show file tree
Hide file tree
Showing 15 changed files with 453 additions and 68 deletions.
Binary file added packages/.DS_Store
Binary file not shown.
98 changes: 71 additions & 27 deletions packages/desktop-agent/src/BasicDesktopAgent.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,81 @@
import { AppIdentifier, Context, ContextHandler, DesktopAgent, IntentHandler, Listener } from "@finos/fdc3";
import { DesktopAgentProvider } from "./DesktopAgentProvider";
import { AppIdentifier, AppMetadata, Context, ContextHandler, DesktopAgent, ImplementationMetadata, IntentHandler, IntentResolution, Listener } from "@finos/fdc3";
import { ChannelSupport } from "./channels/ChannelSupport";
import { IntentSupport } from "./intents/IntentSupport";
import { AppSupport } from "./apps/AppSupport";

/**
* This splits out the functionality of the desktop agent into
* provider details, channels and intents concerns.
* app, channels and intents concerns.
*/
export class BasicDesktopAgent implements DesktopAgent {

readonly provider: DesktopAgentProvider
readonly channels: ChannelSupport
readonly intents: IntentSupport
readonly apps: AppSupport
readonly fdc3Version: string
readonly provider: string


constructor(provider: DesktopAgentProvider, channels: ChannelSupport, intents: IntentSupport) {
this.provider = provider
constructor(channels: ChannelSupport, intents: IntentSupport, apps: AppSupport, fdc3Version: string, provider: string) {
this.intents = intents
this.channels = channels
this.apps = apps
this.fdc3Version = fdc3Version
this.provider = provider
}

getInfo() {
return Promise.resolve(this.provider.getImplementationMetadata());
async getInfo() : Promise<ImplementationMetadata>{
const am = await this.apps.getThisAppMetadata()
return {
fdc3Version: this.fdc3Version,
provider: this.provider,
appMetadata: am,
optionalFeatures: {
OriginatingAppMetadata: this.apps.hasOriginatingAppMetadata(),
UserChannelMembershipAPIs: this.channels.hasUserChannelMembershipAPIs(),
DesktopAgentBridging: this.apps.hasDesktopAgentBridging()
}
}
}

async broadcast(context: Context): Promise<void> {
const channel = await this.channels.getUserChannel();
return channel.broadcast(context);
const channel = await this.channels.getUserChannel()
return channel.broadcast(context)
}

async addContextListener(context: ContextHandler | string | null, handler?: ContextHandler): Promise<Listener> {
const theHandler: ContextHandler = handler ? handler : (context as ContextHandler);
const theContextType: string | null = context && handler ? (context as string) : null;
const channel = await this.channels.getUserChannel();
return channel.addContextListener(theContextType, theHandler);
const theHandler: ContextHandler = handler ? handler : (context as ContextHandler)
const theContextType: string | null = context && handler ? (context as string) : null
const channel = await this.channels.getUserChannel()
return channel.addContextListener(theContextType, theHandler)
}

getUserChannels() {
return this.channels.getUserChannels();
return this.channels.getUserChannels()
}

getSystemChannels() {
return this.channels.getUserChannels();
return this.channels.getUserChannels()
}

getOrCreateChannel(channelId: string) {
return this.channels.getOrCreate(channelId);
return this.channels.getOrCreate(channelId)
}

createPrivateChannel() {
return this.channels.createPrivateChannel();
return this.channels.createPrivateChannel()
}

leaveCurrentChannel() {
return this.channels.leaveUserChannel();
return this.channels.leaveUserChannel()
}

joinUserChannel(channel: string) {
return this.channels.joinUserChannel(channel);
joinUserChannel(channelId: string) {
return this.channels.joinUserChannel(channelId)
}

joinChannel(channelId: string) {
return this.channels.joinUserChannel(channelId)
}

getCurrentChannel() {
Expand All @@ -68,18 +87,43 @@ export class BasicDesktopAgent implements DesktopAgent {
}

findIntentsByContext(context: Context) {
return this.intents.findIntentsByContext(context);
return this.intents.findIntentsByContext(context)
}

raiseIntent(intent: string, context: Context, app?: any) {
return this.intents.raiseIntent(intent, context, app);
private ensureAppId(app?: any) : AppIdentifier | undefined {
if (typeof app === "string") {
return {
appId: app
}
} else if (app?.appId) {
return app as AppIdentifier
} else {
return undefined;
}
}

raiseIntentForContext(context: Context, app?: AppIdentifier | undefined) {
//return this.intents.raiseIntentForContext(context, app);
raiseIntent(intent: string, context: Context, app?: any) {
return this.intents.raiseIntent(intent, context, this.ensureAppId(app))
}

addIntentListener(intent: string, handler: IntentHandler) {
return this.intents.addIntentListener(intent, handler);
return this.intents.addIntentListener(intent, handler)
}

raiseIntentForContext(context: Context, app?: any): Promise<IntentResolution> {
return this.intents.raiseIntentForContext(context, this.ensureAppId(app))
}

open(app: any, context?: Context | undefined) {
return this.apps.open(this.ensureAppId(app)!, context)
}

findInstances(app: AppIdentifier) {
return this.apps.findInstances(app)
}

getAppMetadata(app: AppIdentifier): Promise<AppMetadata> {
return this.apps.getAppMetadata(app);
}

}
33 changes: 32 additions & 1 deletion packages/desktop-agent/src/Messaging.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
import { AppIdentifier } from "@finos/fdc3";
import { AgentRequestMessage, AgentResponseMessage, BridgeRequestMessage } from "@finos/fdc3/dist/bridging/BridgingTypes";

export interface Messaging {

post(message: any) : Promise<void>
/**
* Source for outgoing message
*/
getSource(): AppIdentifier

/**
* UUID for outgoing message
*/
createUUid(): string;

/**
* Post an outgoing message
*/
post(message: AgentRequestMessage) : Promise<void>

/**
* Registers a listener for incoming messages.
*
* @param filter A filter to ignore certain messages
* @param action Action to take on non-ignored messages.
*/
register(filter: (m: AgentRequestMessage) => boolean, action: (m: AgentRequestMessage) => void ) : string

/**
* Unregisters a listener with the id given above
* @param id
*/
unregister(id: string)

createMeta()
}
18 changes: 18 additions & 0 deletions packages/desktop-agent/src/apps/AppSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AppIdentifier, AppMetadata, Context } from "@finos/fdc3";


export interface AppSupport {

hasDesktopAgentBridging(): boolean;

hasOriginatingAppMetadata(): boolean;

findInstances(app: AppIdentifier): Promise<Array<AppIdentifier>>

getAppMetadata(app: AppIdentifier): Promise<AppMetadata>

open(app: AppIdentifier, context?: Context) : Promise<AppIdentifier>

getThisAppMetadata(): Promise<AppMetadata>

}
6 changes: 6 additions & 0 deletions packages/desktop-agent/src/apps/DefaultAppSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AppSupport } from "./AppSupport";


export class DefaultAppSupport implements AppSupport {

}
2 changes: 2 additions & 0 deletions packages/desktop-agent/src/channels/ChannelSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Channel, PrivateChannel, getCurrentChannel } from "@finos/fdc3"

export interface ChannelSupport {

hasUserChannelMembershipAPIs(): boolean

getUserChannel() : Promise<Channel>

getUserChannels() : Promise<Channel[]>
Expand Down
38 changes: 0 additions & 38 deletions packages/desktop-agent/src/channels/ChannelSupportImpl.ts

This file was deleted.

73 changes: 73 additions & 0 deletions packages/desktop-agent/src/channels/DefaultChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Channel, Context, ContextHandler, DisplayMetadata, Listener } from "@finos/fdc3"
import { Messaging } from "../Messaging"
import { BroadcastAgentRequest } from "@finos/fdc3/dist/bridging/BridgingTypes"
import { DefaultContextListener } from "./DefaultContextListener"

export class DefaultChannel implements Channel {

readonly messaging: Messaging
readonly id: string
readonly type: "user" | "app" | "private"
readonly displayMetadata?: DisplayMetadata | undefined;

readonly latestContextMap: Map<string, Context> = new Map()
readonly latestContext: Context | null = null
readonly listeners: Listener[] = []

constructor(messaging: Messaging, id: string, type: "user" | "app" | "private", displayMetadata? : DisplayMetadata) {
this.messaging = messaging
this.id = id
this.type = type
this.displayMetadata = displayMetadata
}

broadcast(context: Context): Promise<void> {
const message : BroadcastAgentRequest = {
meta: {
requestUuid: this.messaging.createUUid(),
timestamp: new Date(),
source: this.messaging.getSource()
},
payload: {
channelId : this.id,
context
},
type: "broadcastRequest"
}
return this.messaging.post(message);
}

getCurrentContext(contextType?: string | undefined): Promise<Context | null> {
if (contextType) {
return Promise.resolve(this.latestContextMap.get(contextType) ?? null)
} else {
return Promise.resolve(this.latestContext);
}
}

addContextListener(contextType: any, handler?: ContextHandler): Promise<Listener> {
let theContextType : string | null
let theHandler: ContextHandler

if (contextType == null) {
theContextType = null;
theHandler = handler as ContextHandler;
} else if (typeof contextType === 'string') {
theContextType = contextType
theHandler = handler as ContextHandler;
} else {
// deprecated one-arg version
theContextType = null;
theHandler = contextType as ContextHandler;
}

return this.addContextListenerInner(theContextType, theHandler);
}

addContextListenerInner(contextType: string | null, theHandler: ContextHandler): Promise<Listener> {
const listener = new DefaultContextListener(this.messaging, "broadcastRequest", this.id, contextType, theHandler);
this.listeners.push(listener)
return Promise.resolve(listener)
}
}

48 changes: 48 additions & 0 deletions packages/desktop-agent/src/channels/DefaultChannelSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Channel, Context, ContextHandler, DisplayMetadata, Listener, PrivateChannel } from "@finos/fdc3";
import { Messaging } from "../Messaging";
import { ChannelSupport } from "./ChannelSupport";
import { BridgeRequestMessage, BroadcastAgentRequest } from "@finos/fdc3/dist/bridging/BridgingTypes";
import { DefaultPrivateChannel } from "./DefaultPrivateChannel";

export class DefaultChannelSupport implements ChannelSupport {

readonly messaging: Messaging
private userChannelId: string

constructor(messaging: Messaging) {
this.messaging = messaging;
}

hasUserChannelMembershipAPIs(): boolean {
return true
}

getUserChannel() : Promise<Channel> {

}

getUserChannels() : Promise<Channel[]> {

}

getDisplayMetadata(id: string) : DisplayMetadata {
return {

}
}

getOrCreate(id: string) : Promise<Channel> {
const out = new DefaultChannel(this.messaging, id, "app", this.getDisplayMetadata(id))
return Promise.resolve(out)
}

createPrivateChannel() : Promise<PrivateChannel> {
const out = new DefaultPrivateChannel(this.messaging, this.messaging.createUUid())
return Promise.resolve(out);
}

leaveUserChannel() : Promise<void>

joinUserChannel(id: string)

}
Loading

0 comments on commit b497a8c

Please sign in to comment.