import type { AppIdentifier, AppIntent, BrowserTypes, Context, DesktopAgent, DesktopAgent as FinosDesktopAgent, FDC3Event, FDC3EventTypes, GetAgentLogLevels, Intent, IntentHandler, Listener, PrivateChannelEvent } from '@finos/fdc3'; import { AppDirectoryApplication, IMSHostManifest, LocalAppDirectory } from './app-directory.contracts.js'; export type RequestMessage = BrowserTypes.AddContextListenerRequest | BrowserTypes.AddIntentListenerRequest | BrowserTypes.BroadcastRequest | BrowserTypes.CreatePrivateChannelRequest | BrowserTypes.FindInstancesRequest | BrowserTypes.FindIntentRequest | BrowserTypes.FindIntentsByContextRequest | BrowserTypes.GetAppMetadataRequest | BrowserTypes.GetCurrentChannelRequest | BrowserTypes.GetInfoRequest | BrowserTypes.GetOrCreateChannelRequest | BrowserTypes.GetUserChannelsRequest | BrowserTypes.JoinUserChannelRequest | BrowserTypes.LeaveCurrentChannelRequest | BrowserTypes.OpenRequest | BrowserTypes.RaiseIntentRequest | BrowserTypes.RaiseIntentForContextRequest | BrowserTypes.GetCurrentContextRequest | BrowserTypes.ContextListenerUnsubscribeRequest | BrowserTypes.IntentListenerUnsubscribeRequest | BrowserTypes.PrivateChannelDisconnectRequest | BrowserTypes.AddEventListenerRequest | BrowserTypes.EventListenerUnsubscribeRequest | BrowserTypes.HeartbeatAcknowledgementRequest | BrowserTypes.IntentResultRequest | BrowserTypes.PrivateChannelUnsubscribeEventListenerRequest | BrowserTypes.PrivateChannelAddEventListenerRequest; export type ResponseMessage = BrowserTypes.AddContextListenerResponse | BrowserTypes.AddIntentListenerResponse | BrowserTypes.BroadcastResponse | BrowserTypes.CreatePrivateChannelResponse | BrowserTypes.FindInstancesResponse | BrowserTypes.FindIntentResponse | BrowserTypes.GetAppMetadataResponse | BrowserTypes.GetCurrentChannelResponse | BrowserTypes.GetInfoResponse | BrowserTypes.GetOrCreateChannelResponse | BrowserTypes.GetUserChannelsResponse | BrowserTypes.JoinUserChannelResponse | BrowserTypes.LeaveCurrentChannelResponse | BrowserTypes.OpenResponse | BrowserTypes.RaiseIntentResponse | BrowserTypes.RaiseIntentForContextResponse | BrowserTypes.RaiseIntentResultResponse | BrowserTypes.ContextListenerUnsubscribeResponse | BrowserTypes.IntentListenerUnsubscribeResponse | BrowserTypes.ContextListenerUnsubscribeResponse | BrowserTypes.IntentListenerUnsubscribeResponse | BrowserTypes.GetCurrentContextResponse | BrowserTypes.FindIntentsByContextResponse | BrowserTypes.EventListenerUnsubscribeResponse | BrowserTypes.IntentResultResponse | BrowserTypes.AddEventListenerResponse | BrowserTypes.PrivateChannelUnsubscribeEventListenerResponse | BrowserTypes.PrivateChannelAddEventListenerResponse | BrowserTypes.PrivateChannelDisconnectResponse; export type EventMessage = BrowserTypes.PrivateChannelOnAddContextListenerEvent | BrowserTypes.PrivateChannelOnUnsubscribeEvent | BrowserTypes.PrivateChannelOnDisconnectEvent | BrowserTypes.BroadcastEvent | BrowserTypes.IntentEvent | BrowserTypes.ChannelChangedEvent | BrowserTypes.HeartbeatEvent | FDC3Event | PrivateChannelEvent; export type HandshakeMessage = BrowserTypes.WebConnectionProtocol1Hello | BrowserTypes.WebConnectionProtocol3Handshake | BrowserTypes.WebConnectionProtocol4ValidateAppIdentity | BrowserTypes.WebConnectionProtocol5ValidateAppIdentitySuccessResponse; export type UIProviderFactory = (agent: Promise) => Promise; export type AppResolverFactory = (agent: Promise) => Promise; export type MessagingProviderFactory = () => Promise; export type Message = RequestMessage | ResponseMessage | EventMessage | HandshakeMessage; /** * A Response or Event message sent from the root app usually in response to a request message received from a proxy agent */ export type IRootOutgoingMessageEnvelope = { channelIds: [string, ...string[]]; payload: ResponseMessage | EventMessage | BrowserTypes.WebConnectionProtocol5ValidateAppIdentitySuccessResponse; }; /** * An incoming message to the root agent from a proxy */ export interface IRootIncomingMessageEnvelope { payload: T; /** * Indicates which channel (which maps to a given proxy agent) the message was received from */ channelId: string; } /** * A Request message sent from a proxy agent. No target information is required as all request messages go to the root */ export type IProxyOutgoingMessageEnvelope = { payload: RequestMessage | BrowserTypes.WebConnectionProtocol4ValidateAppIdentity | BrowserTypes.WebConnectionProtocol6Goodbye; }; /** * A Request message sent from a proxy agent. No target information is required as all request messages go to the root */ export type IProxyIncomingMessageEnvelope = { payload: ResponseMessage | EventMessage | BrowserTypes.WebConnectionProtocol5ValidateAppIdentitySuccessResponse; }; /** * A callback function for passing incoming messages to a registered subscriber */ export type IncomingMessageCallback> = (message: T) => void; /** * Allows root agent to publish messages to and receive messages from proxy agents */ export interface IRootMessagingProvider { /** * Publishes a message to one of more target proxy agents * @param message */ publish(message: IRootOutgoingMessageEnvelope): void; subscribe(callback: IncomingMessageCallback>): void; } /** * Allows proxy agents to receive messages from the root */ export interface IProxyMessagingProvider { /** * sends a request message to the root agent */ sendMessage(message: IProxyOutgoingMessageEnvelope): void; addResponseHandler(callback: IncomingMessageCallback): void; } /** * Extends the FDC3 DesktopAgent interface with features planned for the next version of FDC3. */ export interface DesktopAgentNext extends FinosDesktopAgent { /** * Allows the registration of an intent handler that only triggers when a specific context type or set of context types is passed with the intent * This matches the behavior of intent handlers registered through the app directory * @param intent * @param contextType * @param handler */ addIntentListenerWithContext(intent: Intent, contextType: string | string[], handler: IntentHandler): Promise; } export type AppIdentifierListenerPair = { appIdentifier: FullyQualifiedAppIdentifier; listenerUUID: string; }; export type EventListenerKey = FDC3EventTypes | 'allEvents'; export type EventListenerLookup = Partial>; export type UnqualifiedAppIdentifier = Omit; export type FullyQualifiedAppIdentifier = Required>; export type FullyQualifiedAppId = `${string}@${string}`; export type AppHostManifestLookup = Partial>; export type ResolveForIntentPayload = { context: Context; appIdentifier?: UnqualifiedAppIdentifier; intent: Intent; appManifests: AppHostManifestLookup; /** * Optional app intent data which contains a list of apps and app instances. If this is not passed the resolver should lookup the list of apps and app instances using desktopAgent.findIntent() */ appIntent?: AppIntent; }; export type ResolveForContextPayload = { context: Context; appIdentifier?: UnqualifiedAppIdentifier; appManifests: AppHostManifestLookup; /** * Optional list of app intents for this context that each contain a list of apps and app instances. If this is not passed the resolver should lookup the list of apps and app instances using desktopAgent.findIntentsByContext() */ appIntents?: AppIntent[]; }; export type ResolveForIntentResponse = { app: AppIdentifier; }; export type ResolveForContextResponse = { intent: Intent; app: AppIdentifier; }; /** * Provides a mechanism for resolving an app from an unqualified identifier, an intent, a context or a combination. * * Resolvers are responsible for selecting an app or an existing instance of an app * They may return: * - A FullyQualifiedAppIdentifier (with instanceId) if an existing instance was selected * - An AppIdentifier (without instanceId) if a new instance of an app should be opened * */ export interface IAppResolver { /** * Resolves an app in response to a raiseIntent() function call */ resolveAppForIntent(payload: ResolveForIntentPayload): Promise; /** * resolves an app in response to a raiseIntentForContext() function call */ resolveAppForContext(payload: ResolveForContextPayload): Promise; } /** * Allows a desktop agent to launch an app resolution UI that allows the user to pick which app instance should be used to handle whatever intent has been raised */ export interface IUIProvider extends IAppResolver { } export type BackoffRetryParams = { /** * The maximum number of attempts to retry the connection. This includes the first attempt. */ maxAttempts?: number; /** * The initial delay in milliseconds before the first retry attempt. This will increase exponentially with each attempt */ baseDelay?: number; }; export type RootDesktopAgentFactoryParams = { /** * Either a fully qualified appId (appId@hostname) or an unqualified appId (appId only). If an unqualified appId is provided the hostname of the current window will be used to create a fully qualified appId */ rootAppId: string; messagingProviderFactory?: MessagingProviderFactory; uiProvider?: UIProviderFactory; appDirectoryEntries?: (string | LocalAppDirectory)[]; applicationStrategies?: DesktopAgentStrategies[]; identityUrl?: string; /** * retry parameters for the root agent to retry loading the app directory urls */ backoffRetry?: BackoffRetryParams; logLevels?: GetAgentLogLevels; /** * Optional app directory entry for the root application. When provided this will be used when the root app is added to the application directory, allowing consumers to specify intents the root agent listens for via the interop property. * The appId field is omitted as it is derived from rootAppId. */ appDirectoryEntry?: Omit; }; export type ProxyDesktopAgentFactoryParams = { appIdentifier: FullyQualifiedAppIdentifier; messagingProviderFactory: MessagingProviderFactory; logLevels?: GetAgentLogLevels; }; export type ApplicationStrategyParams = { appDirectoryRecord: Omit; agent: DesktopAgent; /** * manifest from the app directory record identified by the strategy's manifestKey */ manifest?: unknown; context?: Context; }; export type OpenApplicationStrategyResolverParams = ApplicationStrategyParams & { appReadyPromise: Promise; }; export type DesktopAgentStrategies = IOpenApplicationStrategy | ISelectApplicationStrategy; /** * Replaces the default mechanism used to open new applications * This is triggered by agent.open(), agent.raiseIntent() and agent.raiseIntentForContext() */ export interface IOpenApplicationStrategy { /** * Used to identify the manifest key that is used to lookup the specific manifest from the appDirectory record's hostManifests * The manifest identified through this key will then be passed to the open() and canOpen() functions */ manifestKey?: string; /** * if the strategy is able to open a given application returns true * If false is returned the strategy will not be used by the desktop agent and the next one will be tried */ canOpen(params: ApplicationStrategyParams): Promise; /** * Opens a new window and returns a promise that resolves to the connectionAttemptUUid of the new window * TODO: support multiple connection attempts for each window - use a callback to notify the caller of the connection attempt rather than returning a promise * @param params */ open(params: OpenApplicationStrategyResolverParams): Promise; } export type SelectApplicationStrategyParams = { appDirectoryRecord?: Omit; agent: DesktopAgent; /** * manifest from the app directory record identified by the strategy's manifestKey */ manifest?: unknown; context?: Context; appIdentifier: FullyQualifiedAppIdentifier; }; /** * allows an application that has already been opened to be selected or focussed * This might involve restoring a minimised window or bringing a window to the front so that it is visible to the user */ export interface ISelectApplicationStrategy { /** * Used to identify the manifest key that is used to lookup the specific manifest from the appDirectory record's hostManifests * The manifest identified through this key will then be passed to the open() and canOpen() functions */ manifestKey?: string; /** * if the strategy is able to open a given application returns true * If false is returned the strategy will not be used by the desktop agent and the next one will be tried */ canSelectApp(params: SelectApplicationStrategyParams): Promise; /** * Opens a new window and returns a promise that resolves to the connectionAttemptUUid of the new window * TODO: support multiple connection attempts for each window - use a callback to notify the caller of the connection attempt rather than returning a promise * @param params */ selectApp(params: SelectApplicationStrategyParams): Promise; } /** * Used as an instanceId when calling `raiseIntent` or `raiseIntentForContext` to force the desktop agent to create a new instance of the app. * There is currently no way to tell the agent to create a new instance of a given app using the current spec. * If only an appId is sent as the appIdentifier (e.g. `{ appId: "my-app-id" }`), then the agent will typically show a resolver UI with multiple existing instances and a "create new instance" option. * This is a temporary solution until the issue in the FDC3 spec is resolved. * * Issue raised: https://github.com/finos/FDC3/issues/1940 * * raiseIntent("my-intent", {id: "my-context"}, {appId: "my-app", instanceId: FORCE_NEW_INSTANCE}); * */ export declare const FORCE_NEW_INSTANCE = "ms.fdc3-web.desktop-agent.force-new-app-instance";