@openfin/core 29.72.18 → 29.73.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OpenFin.d.ts +40 -23
- package/package.json +1 -1
- package/src/api/application/Factory.js +3 -3
- package/src/api/application/index.js +7 -3
- package/src/api/base.js +18 -20
- package/src/api/external-application/index.js +7 -3
- package/src/api/fin.js +2 -2
- package/src/api/frame/Factory.js +2 -2
- package/src/api/frame/index.js +7 -3
- package/src/api/interappbus/channel/client.js +24 -26
- package/src/api/interappbus/channel/connection-manager.js +24 -26
- package/src/api/interappbus/channel/index.js +16 -18
- package/src/api/interappbus/channel/protocols/classic/strategy.js +21 -22
- package/src/api/interappbus/channel/protocols/rtc/endpoint.js +24 -26
- package/src/api/interappbus/channel/protocols/rtc/strategy.js +29 -31
- package/src/api/interappbus/channel/provider.js +134 -139
- package/src/api/interappbus/index.js +1 -1
- package/src/api/interop/InteropBroker.js +9 -9
- package/src/api/interop/InteropClient.js +38 -40
- package/src/api/interop/SessionContextGroupClient.js +22 -24
- package/src/api/interop/fdc3/PrivateChannelClient.d.ts +17 -0
- package/src/api/interop/fdc3/PrivateChannelClient.js +82 -0
- package/src/api/interop/fdc3/PrivateChannelProvider.d.ts +40 -0
- package/src/api/interop/fdc3/PrivateChannelProvider.js +224 -0
- package/src/api/interop/fdc3/fdc3-1.2.d.ts +0 -1
- package/src/api/interop/fdc3/fdc3-1.2.js +1 -27
- package/src/api/interop/fdc3/fdc3-2.0.d.ts +20 -1
- package/src/api/interop/fdc3/fdc3-2.0.js +29 -4
- package/src/api/interop/fdc3/utils.d.ts +4 -0
- package/src/api/interop/fdc3/utils.js +112 -4
- package/src/api/interop/index.js +7 -3
- package/src/api/interop/utils.js +20 -14
- package/src/api/platform/Factory.js +5 -5
- package/src/api/platform/Instance.js +11 -12
- package/src/api/platform/index.js +7 -3
- package/src/api/platform/layout/Factory.js +18 -20
- package/src/api/platform/layout/Instance.d.ts +1 -1
- package/src/api/platform/layout/Instance.js +2 -2
- package/src/api/platform/layout/controllers/splitter-controller.js +1 -1
- package/src/api/platform/layout/controllers/tab-drag-controller.d.ts +17 -8
- package/src/api/platform/layout/controllers/tab-drag-controller.js +44 -22
- package/src/api/platform/layout/index.js +7 -3
- package/src/api/platform/layout/utils/bounds-observer.js +5 -3
- package/src/api/snapshot-source/Factory.js +1 -1
- package/src/api/snapshot-source/Instance.js +33 -35
- package/src/api/snapshot-source/index.js +7 -3
- package/src/api/snapshot-source/utils.js +2 -1
- package/src/api/view/Factory.js +2 -2
- package/src/api/view/Instance.d.ts +31 -1
- package/src/api/view/Instance.js +31 -1
- package/src/api/view/index.js +7 -3
- package/src/api/window/Factory.js +2 -2
- package/src/api/window/Instance.d.ts +3 -0
- package/src/api/window/Instance.js +3 -0
- package/src/api/window/index.js +7 -3
- package/src/environment/node-env.js +2 -2
- package/src/environment/openfin-env.js +15 -17
- package/src/fdc3.js +1 -1
- package/src/mock.js +1 -2
- package/src/transport/transport.js +26 -28
- package/src/transport/wire.d.ts +9 -7
- package/src/util/http.d.ts +1 -1
- package/src/util/http.js +16 -11
- package/src/util/normalize-config.js +5 -5
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrivateChannelProvider = void 0;
|
|
4
|
+
const InteropBroker_1 = require("../InteropBroker");
|
|
5
|
+
class PrivateChannelProvider {
|
|
6
|
+
constructor(provider, id) {
|
|
7
|
+
this.provider = provider;
|
|
8
|
+
this.id = id;
|
|
9
|
+
this.clients = new Map();
|
|
10
|
+
this.registerListeners();
|
|
11
|
+
this.contextByContextType = new Map();
|
|
12
|
+
this.lastContext = undefined;
|
|
13
|
+
this.provider.onConnection((clientIdentity) => this.registerNewClient(clientIdentity));
|
|
14
|
+
this.provider.onDisconnection((clientIdentity) => this.clients.delete(clientIdentity.endpointId));
|
|
15
|
+
}
|
|
16
|
+
getClientState(id) {
|
|
17
|
+
return this.clients.get(id.endpointId);
|
|
18
|
+
}
|
|
19
|
+
registerListeners() {
|
|
20
|
+
this.provider.register('broadcast', this.broadcast.bind(this));
|
|
21
|
+
this.provider.register('getCurrentContext', this.getCurrentContext.bind(this));
|
|
22
|
+
this.provider.register('contextHandlerAdded', this.contextHandlerAdded.bind(this));
|
|
23
|
+
this.provider.register('contextHandlerRemoved', this.contextHandlerRemoved.bind(this));
|
|
24
|
+
this.provider.register('nonStandardHandlerRemoved', this.nonStandardHandlerRemoved.bind(this));
|
|
25
|
+
this.provider.register('onAddContextHandlerAdded', this.onAddContextHandlerAdded.bind(this));
|
|
26
|
+
this.provider.register('onDisconnectHandlerAdded', this.onDisconnectHandlerAdded.bind(this));
|
|
27
|
+
this.provider.register('onUnsubscribeHandlerAdded', this.onUnsubscribeHandlerAdded.bind(this));
|
|
28
|
+
this.provider.register('clientDisconnecting', this.clientDisconnecting.bind(this));
|
|
29
|
+
}
|
|
30
|
+
broadcast(payload, broadcasterClientIdentity) {
|
|
31
|
+
const { context } = payload;
|
|
32
|
+
const broadcasterClientState = this.getClientState(broadcasterClientIdentity);
|
|
33
|
+
if (!broadcasterClientState) {
|
|
34
|
+
throw new Error(`Client with Identity: ${broadcasterClientIdentity.uuid} ${broadcasterClientIdentity.name}, tried to call broadcast, is not connected to this Private Channel`);
|
|
35
|
+
}
|
|
36
|
+
const contextIntegrityCheckResult = InteropBroker_1.InteropBroker.checkContextIntegrity(context);
|
|
37
|
+
if (contextIntegrityCheckResult.isValid === false) {
|
|
38
|
+
throw new Error(`Failed to broadcast - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`);
|
|
39
|
+
}
|
|
40
|
+
this.contextByContextType.set(context.type, context);
|
|
41
|
+
this.lastContext = context;
|
|
42
|
+
Array.from(this.clients.values()).forEach((currClientState) => {
|
|
43
|
+
const handlerIdsForContextType = currClientState.handlerIdsByContextTypes.get(context.type);
|
|
44
|
+
if (handlerIdsForContextType) {
|
|
45
|
+
handlerIdsForContextType.forEach((handlerId) => {
|
|
46
|
+
this.provider.dispatch(currClientState.clientIdentity, handlerId, context);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (currClientState.globalHandler) {
|
|
50
|
+
this.provider.dispatch(currClientState.clientIdentity, currClientState.globalHandler, context);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
getCurrentContext(payload, senderClientIdentity) {
|
|
55
|
+
const { contextType } = payload;
|
|
56
|
+
const clientState = this.getClientState(senderClientIdentity);
|
|
57
|
+
if (!clientState) {
|
|
58
|
+
throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call getCurrentContext, is not connected to this Private Channel`);
|
|
59
|
+
}
|
|
60
|
+
if (contextType !== undefined) {
|
|
61
|
+
const currentContext = this.contextByContextType.get(contextType);
|
|
62
|
+
if (currentContext)
|
|
63
|
+
return currentContext;
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return this.lastContext ? this.lastContext : null;
|
|
67
|
+
}
|
|
68
|
+
contextHandlerAdded(payload, senderClientIdentity) {
|
|
69
|
+
const { handlerId, contextType } = payload;
|
|
70
|
+
const senderClientState = this.getClientState(senderClientIdentity);
|
|
71
|
+
if (!senderClientState) {
|
|
72
|
+
throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call addContextListener, is not connected to this Private Channel`);
|
|
73
|
+
}
|
|
74
|
+
if (contextType) {
|
|
75
|
+
const currentHandlersList = senderClientState.handlerIdsByContextTypes.get(contextType) || [];
|
|
76
|
+
senderClientState.handlerIdsByContextTypes.set(contextType, [...currentHandlersList, handlerId]);
|
|
77
|
+
const currContext = this.contextByContextType.get(contextType);
|
|
78
|
+
if (currContext) {
|
|
79
|
+
this.provider.dispatch(senderClientIdentity, handlerId, currContext);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
senderClientState.globalHandler = handlerId;
|
|
84
|
+
if (this.lastContext) {
|
|
85
|
+
this.provider.dispatch(senderClientIdentity, handlerId, this.lastContext);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
Array.from(this.clients.values()).forEach((currClientState) => {
|
|
89
|
+
if (currClientState.clientIdentity.endpointId !== senderClientIdentity.endpointId &&
|
|
90
|
+
currClientState.onAddContextListenerHandlerId) {
|
|
91
|
+
this.provider.dispatch(currClientState.clientIdentity, currClientState.onAddContextListenerHandlerId, contextType);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
async contextHandlerRemoved(payload, removingClientIdentity) {
|
|
96
|
+
// MC: Made this removal async to ensure that onUnsubscribe handlers are hit before anything else happens.
|
|
97
|
+
const { handlerId } = payload;
|
|
98
|
+
const removingClientState = this.getClientState(removingClientIdentity);
|
|
99
|
+
if (removingClientState) {
|
|
100
|
+
let contextType;
|
|
101
|
+
if (removingClientState.globalHandler === handlerId) {
|
|
102
|
+
removingClientState.globalHandler = undefined;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
for (const [currContextType, handlersIds] of removingClientState.handlerIdsByContextTypes) {
|
|
106
|
+
const index = handlersIds.indexOf(handlerId);
|
|
107
|
+
if (index > -1) {
|
|
108
|
+
handlersIds.splice(index, 1);
|
|
109
|
+
contextType = currContextType;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const dispatchesToSend = [];
|
|
114
|
+
const otherClientStates = Array.from(this.clients.values());
|
|
115
|
+
for (let i = 0; i < otherClientStates.length; i++) {
|
|
116
|
+
const otherClientState = otherClientStates[i];
|
|
117
|
+
if (otherClientState.clientIdentity.endpointId !== removingClientIdentity.endpointId &&
|
|
118
|
+
otherClientState.onUnsubscribeHandlerId) {
|
|
119
|
+
dispatchesToSend.push(this.provider.dispatch(otherClientState.clientIdentity, otherClientState.onUnsubscribeHandlerId, contextType));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
await Promise.all(dispatchesToSend);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error(`Problem when attempting to dispatch to onUnsubscribeHandlers. Error: ${error} Removing Client: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}`);
|
|
127
|
+
throw new Error(error);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}.`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
nonStandardHandlerRemoved(payload, id) {
|
|
135
|
+
const { handlerId } = payload;
|
|
136
|
+
const clientState = this.getClientState(id);
|
|
137
|
+
if (clientState) {
|
|
138
|
+
if (clientState.onDisconnectHandlerId === handlerId) {
|
|
139
|
+
clientState.onDisconnectHandlerId = undefined;
|
|
140
|
+
}
|
|
141
|
+
else if (clientState.onAddContextListenerHandlerId === handlerId) {
|
|
142
|
+
clientState.onAddContextListenerHandlerId = undefined;
|
|
143
|
+
}
|
|
144
|
+
else if (clientState.onUnsubscribeHandlerId === handlerId) {
|
|
145
|
+
clientState.onUnsubscribeHandlerId = undefined;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. clientIdentity: ${id}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
onAddContextHandlerAdded(payload, senderClientIdentity) {
|
|
153
|
+
const clientState = this.getClientState(senderClientIdentity);
|
|
154
|
+
const { handlerId } = payload;
|
|
155
|
+
if (!clientState) {
|
|
156
|
+
throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call onAddContextListener, is not connected to this Private Channel`);
|
|
157
|
+
}
|
|
158
|
+
clientState.onAddContextListenerHandlerId = handlerId;
|
|
159
|
+
// FDC3 Spec says that the added listener should fire for all previously-registered addContextListeners from the other client
|
|
160
|
+
Array.from(this.clients.values()).forEach((otherClientState) => {
|
|
161
|
+
if (otherClientState.clientIdentity.endpointId !== senderClientIdentity.endpointId) {
|
|
162
|
+
Array.from(otherClientState.handlerIdsByContextTypes.keys()).forEach((subscribedContextType) => {
|
|
163
|
+
this.provider.dispatch(senderClientIdentity, handlerId, subscribedContextType);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
onDisconnectHandlerAdded(payload, id) {
|
|
169
|
+
const clientState = this.getClientState(id);
|
|
170
|
+
const { handlerId } = payload;
|
|
171
|
+
if (!clientState) {
|
|
172
|
+
throw new Error(`Client with Identity: ${id.uuid} ${id.name}, tried to call onDisconnect, is not connected to this Private Channel`);
|
|
173
|
+
}
|
|
174
|
+
clientState.onDisconnectHandlerId = handlerId;
|
|
175
|
+
}
|
|
176
|
+
onUnsubscribeHandlerAdded(payload, id) {
|
|
177
|
+
const clientState = this.getClientState(id);
|
|
178
|
+
const { handlerId } = payload;
|
|
179
|
+
if (!clientState) {
|
|
180
|
+
throw new Error(`Client with Identity: ${id.uuid} ${id.name}, tried to call onUnsubscribe, is not connected to this Private Channel`);
|
|
181
|
+
}
|
|
182
|
+
clientState.onUnsubscribeHandlerId = handlerId;
|
|
183
|
+
}
|
|
184
|
+
async clientDisconnecting(payload, disconnectingClientIdentity) {
|
|
185
|
+
const disconnectingClientState = this.getClientState(disconnectingClientIdentity);
|
|
186
|
+
if (!disconnectingClientState) {
|
|
187
|
+
throw new Error(`Client with Identity: ${disconnectingClientIdentity.uuid} ${disconnectingClientIdentity.name}, tried to call disconnect, is not connected to this Private Channel`);
|
|
188
|
+
}
|
|
189
|
+
disconnectingClientState.handlerIdsByContextTypes.clear();
|
|
190
|
+
this.clients.delete(disconnectingClientIdentity.endpointId);
|
|
191
|
+
const dispatchesToSend = [];
|
|
192
|
+
// TODO: call onDisconnect Handler of the other client only.
|
|
193
|
+
// CURRENTLY, just calling the onDisconnect handler for all the other clients. Once we limit it to just one other client, we can eliminate all the iteration code.
|
|
194
|
+
const otherClientStates = Array.from(this.clients.values());
|
|
195
|
+
for (let i = 0; i < otherClientStates.length; i++) {
|
|
196
|
+
const otherClientState = otherClientStates[i];
|
|
197
|
+
if (otherClientState.clientIdentity.endpointId !== disconnectingClientIdentity.endpointId &&
|
|
198
|
+
otherClientState.onDisconnectHandlerId) {
|
|
199
|
+
dispatchesToSend.push(this.provider.dispatch(otherClientState.clientIdentity, otherClientState.onDisconnectHandlerId));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
await Promise.all(dispatchesToSend);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
console.error(`Problem when attempting to dispatch to onDisconnectHandlers. Error: ${error} Disconnecting Client: uuid: ${disconnectingClientIdentity.uuid}. name: ${disconnectingClientIdentity.name}. endpointId: ${disconnectingClientIdentity.endpointId}`);
|
|
207
|
+
throw new Error(error);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
registerNewClient(clientIdentity) {
|
|
211
|
+
if (!this.clients.has(clientIdentity.endpointId)) {
|
|
212
|
+
const clientSubscriptionState = {
|
|
213
|
+
clientIdentity,
|
|
214
|
+
handlerIdsByContextTypes: new Map(),
|
|
215
|
+
globalHandler: undefined,
|
|
216
|
+
onAddContextListenerHandlerId: undefined,
|
|
217
|
+
onUnsubscribeHandlerId: undefined,
|
|
218
|
+
onDisconnectHandlerId: undefined
|
|
219
|
+
};
|
|
220
|
+
this.clients.set(clientIdentity.endpointId, clientSubscriptionState);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.PrivateChannelProvider = PrivateChannelProvider;
|
|
@@ -329,7 +329,7 @@ class Fdc3Module extends base_1.Base {
|
|
|
329
329
|
// we do not want to expose this error, just continue if this analytics-only call fails
|
|
330
330
|
});
|
|
331
331
|
const sessionContextGroup = await this.fin.me.interop.joinSessionContextGroup(channelId);
|
|
332
|
-
return
|
|
332
|
+
return (0, utils_1.buildAppChannelObject)(sessionContextGroup);
|
|
333
333
|
}
|
|
334
334
|
/**
|
|
335
335
|
* Returns metadata relating to the FDC3 object and its provider, including the supported version of the FDC3 specification and the name of the provider of the implementation.
|
|
@@ -397,31 +397,5 @@ class Fdc3Module extends base_1.Base {
|
|
|
397
397
|
}
|
|
398
398
|
};
|
|
399
399
|
}
|
|
400
|
-
// eslint-disable-next-line class-methods-use-this
|
|
401
|
-
buildAppChannelObject(sessionContextGroup) {
|
|
402
|
-
return {
|
|
403
|
-
id: sessionContextGroup.id,
|
|
404
|
-
type: 'app',
|
|
405
|
-
broadcast: sessionContextGroup.setContext,
|
|
406
|
-
getCurrentContext: async (contextType) => {
|
|
407
|
-
const context = await sessionContextGroup.getCurrentContext(contextType);
|
|
408
|
-
return context === undefined ? null : context;
|
|
409
|
-
},
|
|
410
|
-
addContextListener: (contextType, handler) => {
|
|
411
|
-
let listener;
|
|
412
|
-
if (typeof contextType === 'function') {
|
|
413
|
-
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
414
|
-
listener = sessionContextGroup.addContextHandler(contextType);
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
listener = sessionContextGroup.addContextHandler(handler, contextType === null ? undefined : contextType);
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
...listener,
|
|
421
|
-
unsubscribe: () => listener.then((l) => l.unsubscribe())
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
400
|
}
|
|
427
401
|
exports.default = Fdc3Module;
|
|
@@ -102,6 +102,20 @@ import Transport from '../../../transport/transport';
|
|
|
102
102
|
* @property { string } [version] The version number of the Intents schema being used.
|
|
103
103
|
* @property { Function } getResult {@link getResult Function} that returns a promise that will resolve to either `Context` data returned by the application that resolves the raised intent or a `Channel` established and returned by the app resolving the intent.
|
|
104
104
|
*/
|
|
105
|
+
/**
|
|
106
|
+
* @typedef { object } PrivateChannel
|
|
107
|
+
* @summary 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.
|
|
108
|
+
* @property { string } id Private Channel Id
|
|
109
|
+
* @property { string } type Channel Type
|
|
110
|
+
* @property { DisplayMetadata } [displayMetadata]
|
|
111
|
+
* @property { function } broadcast
|
|
112
|
+
* @property { function } getCurrentContext
|
|
113
|
+
* @property { function } addContextListener
|
|
114
|
+
* @property { function } onAddContextListener
|
|
115
|
+
* @property { function } onUnsubscribe
|
|
116
|
+
* @property { function } onDisconnect
|
|
117
|
+
* @property { function } disconnect
|
|
118
|
+
*/
|
|
105
119
|
/**
|
|
106
120
|
* @class
|
|
107
121
|
* @alias fdc3v2
|
|
@@ -229,7 +243,12 @@ export default class Fdc3Module2 extends Base implements FDC3v2.DesktopAgent {
|
|
|
229
243
|
* @tutorial fdc3.getOrCreateChannel
|
|
230
244
|
*/
|
|
231
245
|
getOrCreateChannel(channelId: string): Promise<FDC3.Channel>;
|
|
232
|
-
|
|
246
|
+
/**
|
|
247
|
+
* 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.
|
|
248
|
+
* @returns { Promise<PrivateChannel> }
|
|
249
|
+
* @tutorial fdc3v2.createPrivateChannel
|
|
250
|
+
*/
|
|
251
|
+
createPrivateChannel(): Promise<FDC3v2.PrivateChannel>;
|
|
233
252
|
/**
|
|
234
253
|
* Retrieves a list of the User Channels available for the app to join.
|
|
235
254
|
* @returns { Promise<Channel[]>}
|
|
@@ -5,6 +5,8 @@ const utils_1 = require("../utils");
|
|
|
5
5
|
const InteropClient_1 = require("../InteropClient");
|
|
6
6
|
const utils_2 = require("./utils");
|
|
7
7
|
const fdc3_1_2_1 = require("./fdc3-1.2");
|
|
8
|
+
const PrivateChannelClient_1 = require("./PrivateChannelClient");
|
|
9
|
+
const PrivateChannelProvider_1 = require("./PrivateChannelProvider");
|
|
8
10
|
/**
|
|
9
11
|
* @typedef { object } AppIdentifier
|
|
10
12
|
* @summary Identifies an application, or instance of an application, and is used to target FDC3 API calls at specific applications.
|
|
@@ -107,6 +109,20 @@ const fdc3_1_2_1 = require("./fdc3-1.2");
|
|
|
107
109
|
* @property { string } [version] The version number of the Intents schema being used.
|
|
108
110
|
* @property { Function } getResult {@link getResult Function} that returns a promise that will resolve to either `Context` data returned by the application that resolves the raised intent or a `Channel` established and returned by the app resolving the intent.
|
|
109
111
|
*/
|
|
112
|
+
/**
|
|
113
|
+
* @typedef { object } PrivateChannel
|
|
114
|
+
* @summary 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.
|
|
115
|
+
* @property { string } id Private Channel Id
|
|
116
|
+
* @property { string } type Channel Type
|
|
117
|
+
* @property { DisplayMetadata } [displayMetadata]
|
|
118
|
+
* @property { function } broadcast
|
|
119
|
+
* @property { function } getCurrentContext
|
|
120
|
+
* @property { function } addContextListener
|
|
121
|
+
* @property { function } onAddContextListener
|
|
122
|
+
* @property { function } onUnsubscribe
|
|
123
|
+
* @property { function } onDisconnect
|
|
124
|
+
* @property { function } disconnect
|
|
125
|
+
*/
|
|
110
126
|
/**
|
|
111
127
|
* @class
|
|
112
128
|
* @alias fdc3v2
|
|
@@ -289,7 +305,7 @@ class Fdc3Module2 extends base_1.Base {
|
|
|
289
305
|
// we do not want to expose this error, just continue if this analytics-only call fails
|
|
290
306
|
});
|
|
291
307
|
try {
|
|
292
|
-
return utils_2.getIntentResolution(this.fin.me.interop, context, app, intent);
|
|
308
|
+
return (0, utils_2.getIntentResolution)(this.fin.me.interop, context, app, intent);
|
|
293
309
|
}
|
|
294
310
|
catch (error) {
|
|
295
311
|
const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error;
|
|
@@ -309,7 +325,7 @@ class Fdc3Module2 extends base_1.Base {
|
|
|
309
325
|
// we do not want to expose this error, just continue if this analytics-only call fails
|
|
310
326
|
});
|
|
311
327
|
try {
|
|
312
|
-
return utils_2.getIntentResolution(this.fin.me.interop, context, app);
|
|
328
|
+
return (0, utils_2.getIntentResolution)(this.fin.me.interop, context, app);
|
|
313
329
|
}
|
|
314
330
|
catch (error) {
|
|
315
331
|
const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error;
|
|
@@ -366,9 +382,18 @@ class Fdc3Module2 extends base_1.Base {
|
|
|
366
382
|
async getOrCreateChannel(channelId) {
|
|
367
383
|
return this.fdc3Module.getOrCreateChannel(channelId);
|
|
368
384
|
}
|
|
369
|
-
|
|
385
|
+
/**
|
|
386
|
+
* 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.
|
|
387
|
+
* @returns { Promise<PrivateChannel> }
|
|
388
|
+
* @tutorial fdc3v2.createPrivateChannel
|
|
389
|
+
*/
|
|
370
390
|
async createPrivateChannel() {
|
|
371
|
-
|
|
391
|
+
const channelId = (0, utils_1.generateId)();
|
|
392
|
+
const channelProvider = await this.fin.InterApplicationBus.Channel.create(channelId);
|
|
393
|
+
const newPrivateChannelProvider = new PrivateChannelProvider_1.PrivateChannelProvider(channelProvider, channelId);
|
|
394
|
+
const channelClient = await this.fin.InterApplicationBus.Channel.connect(channelId);
|
|
395
|
+
const newPrivateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId);
|
|
396
|
+
return (0, utils_2.buildPrivateChannelObject)(newPrivateChannelClient);
|
|
372
397
|
}
|
|
373
398
|
/**
|
|
374
399
|
* Retrieves a list of the User Channels available for the app to join.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PrivateChannelClient } from './PrivateChannelClient';
|
|
1
2
|
export declare class UnsupportedChannelApiError extends Error {
|
|
2
3
|
constructor(apiName: string);
|
|
3
4
|
}
|
|
@@ -11,4 +12,7 @@ export declare enum ResultError {
|
|
|
11
12
|
*/
|
|
12
13
|
IntentHandlerRejected = "IntentHandlerRejected"
|
|
13
14
|
}
|
|
15
|
+
export declare const buildPrivateChannelObject: (privateChannelClient: PrivateChannelClient) => FDC3v2.PrivateChannel;
|
|
16
|
+
export declare const buildAppChannelObject: (sessionContextGroup: OpenFin.SessionContextGroup) => FDC3.Channel;
|
|
17
|
+
export declare const connectPrivateChannel: (channelId: string) => Promise<FDC3v2.PrivateChannel>;
|
|
14
18
|
export declare const getIntentResolution: (interopModule: OpenFin.InteropClient, context: OpenFin.Context, app?: FDC3v2.AppIdentifier | FDC3.TargetApp, intent?: string) => Promise<FDC3v2.IntentResolution>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getIntentResolution = exports.ResultError = exports.UnsupportedChannelApiError = void 0;
|
|
3
|
+
exports.getIntentResolution = exports.connectPrivateChannel = exports.buildAppChannelObject = exports.buildPrivateChannelObject = exports.ResultError = exports.UnsupportedChannelApiError = void 0;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
|
+
const PrivateChannelClient_1 = require("./PrivateChannelClient");
|
|
5
6
|
class UnsupportedChannelApiError extends Error {
|
|
6
7
|
constructor(apiName) {
|
|
7
8
|
super(apiName);
|
|
@@ -20,10 +21,97 @@ var ResultError;
|
|
|
20
21
|
*/
|
|
21
22
|
ResultError["IntentHandlerRejected"] = "IntentHandlerRejected";
|
|
22
23
|
})(ResultError = exports.ResultError || (exports.ResultError = {}));
|
|
23
|
-
|
|
24
|
+
const buildPrivateChannelObject = (privateChannelClient) => {
|
|
25
|
+
let clientDisconnected = false;
|
|
26
|
+
const checkIfClientDisconnected = () => {
|
|
27
|
+
if (clientDisconnected) {
|
|
28
|
+
throw new Error('Private Channel Client has been disconnected from the Private Channel');
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
id: privateChannelClient.id,
|
|
33
|
+
type: 'private',
|
|
34
|
+
broadcast: async (context) => {
|
|
35
|
+
checkIfClientDisconnected();
|
|
36
|
+
return privateChannelClient.broadcast(context);
|
|
37
|
+
},
|
|
38
|
+
getCurrentContext: async (contextType) => {
|
|
39
|
+
checkIfClientDisconnected();
|
|
40
|
+
return privateChannelClient.getCurrentContext(contextType);
|
|
41
|
+
},
|
|
42
|
+
addContextListener: async (contextType, handler) => {
|
|
43
|
+
checkIfClientDisconnected();
|
|
44
|
+
let handlerInUse = handler;
|
|
45
|
+
let contextTypeInUse = contextType;
|
|
46
|
+
if (typeof contextType === 'function') {
|
|
47
|
+
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
48
|
+
handlerInUse = contextType;
|
|
49
|
+
contextTypeInUse = null;
|
|
50
|
+
}
|
|
51
|
+
const listener = privateChannelClient.addContextListener(contextTypeInUse, handlerInUse);
|
|
52
|
+
return listener;
|
|
53
|
+
},
|
|
54
|
+
onAddContextListener: (handler) => {
|
|
55
|
+
checkIfClientDisconnected();
|
|
56
|
+
return privateChannelClient.onAddContextListener(handler);
|
|
57
|
+
},
|
|
58
|
+
disconnect: async () => {
|
|
59
|
+
checkIfClientDisconnected();
|
|
60
|
+
clientDisconnected = true;
|
|
61
|
+
return privateChannelClient.disconnect();
|
|
62
|
+
},
|
|
63
|
+
onDisconnect: (handler) => {
|
|
64
|
+
checkIfClientDisconnected();
|
|
65
|
+
return privateChannelClient.onDisconnect(handler);
|
|
66
|
+
},
|
|
67
|
+
onUnsubscribe: (handler) => {
|
|
68
|
+
checkIfClientDisconnected();
|
|
69
|
+
return privateChannelClient.onUnsubscribe(handler);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
exports.buildPrivateChannelObject = buildPrivateChannelObject;
|
|
74
|
+
const buildAppChannelObject = (sessionContextGroup) => {
|
|
75
|
+
return {
|
|
76
|
+
id: sessionContextGroup.id,
|
|
77
|
+
type: 'app',
|
|
78
|
+
broadcast: sessionContextGroup.setContext,
|
|
79
|
+
getCurrentContext: async (contextType) => {
|
|
80
|
+
const context = await sessionContextGroup.getCurrentContext(contextType);
|
|
81
|
+
return context === undefined ? null : context;
|
|
82
|
+
},
|
|
83
|
+
addContextListener: (contextType, handler) => {
|
|
84
|
+
let listener;
|
|
85
|
+
if (typeof contextType === 'function') {
|
|
86
|
+
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
87
|
+
listener = sessionContextGroup.addContextHandler(contextType);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
listener = sessionContextGroup.addContextHandler(handler, contextType === null ? undefined : contextType);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
...listener,
|
|
94
|
+
unsubscribe: () => listener.then((l) => l.unsubscribe())
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
exports.buildAppChannelObject = buildAppChannelObject;
|
|
100
|
+
const connectPrivateChannel = async (channelId) => {
|
|
101
|
+
try {
|
|
102
|
+
const channelClient = await fin.InterApplicationBus.Channel.connect(channelId);
|
|
103
|
+
const privateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId);
|
|
104
|
+
return (0, exports.buildPrivateChannelObject)(privateChannelClient);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`Private Channel with id: ${channelId} doesn't exist`);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
exports.connectPrivateChannel = connectPrivateChannel;
|
|
111
|
+
const getIntentResolution = async (interopModule, context, app, intent) => {
|
|
24
112
|
// Generate an ID to make a session context group with. We will pass that ID to the Broker.
|
|
25
113
|
// The broker will then setContext on that session context group later with our Intent Result,
|
|
26
|
-
const guid = utils_1.generateId();
|
|
114
|
+
const guid = (0, utils_1.generateId)();
|
|
27
115
|
// Promise we'll use in getResult
|
|
28
116
|
const getResultPromise = new Promise((resolve) => {
|
|
29
117
|
fin.InterApplicationBus.subscribe({ uuid: '*' }, guid, (intentResult) => {
|
|
@@ -35,13 +123,32 @@ exports.getIntentResolution = async (interopModule, context, app, intent) => {
|
|
|
35
123
|
const intentObj = intent ? { name: intent, context, metadata } : { ...context, metadata };
|
|
36
124
|
// Set up the getResult call.
|
|
37
125
|
const getResult = async () => {
|
|
38
|
-
|
|
126
|
+
let intentResult = await getResultPromise;
|
|
39
127
|
if (!intentResult) {
|
|
40
128
|
throw new Error(ResultError.NoResultReturned);
|
|
41
129
|
}
|
|
42
130
|
if (intentResult instanceof Error) {
|
|
43
131
|
throw new Error(ResultError.IntentHandlerRejected);
|
|
44
132
|
}
|
|
133
|
+
if (typeof intentResult === 'object') {
|
|
134
|
+
const { id, type } = intentResult;
|
|
135
|
+
if (type && id && typeof id === 'string') {
|
|
136
|
+
switch (type) {
|
|
137
|
+
case 'private': {
|
|
138
|
+
intentResult = await (0, exports.connectPrivateChannel)(id);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case 'app': {
|
|
142
|
+
const sessionContextGroup = await interopModule.joinSessionContextGroup(id);
|
|
143
|
+
intentResult = (0, exports.buildAppChannelObject)(sessionContextGroup);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
default: {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
45
152
|
return intentResult;
|
|
46
153
|
};
|
|
47
154
|
// Finally fire the intent.
|
|
@@ -61,3 +168,4 @@ exports.getIntentResolution = async (interopModule, context, app, intent) => {
|
|
|
61
168
|
}
|
|
62
169
|
return { ...intentResolutionInfoFromBroker, getResult };
|
|
63
170
|
};
|
|
171
|
+
exports.getIntentResolution = getIntentResolution;
|
package/src/api/interop/index.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
8
12
|
}));
|
|
9
13
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !
|
|
11
|
-
}
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
12
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
17
|
const Factory_1 = require("./Factory");
|
|
14
18
|
exports.default = Factory_1.default;
|
package/src/api/interop/utils.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wrapIntentHandler = exports.BROKER_ERRORS = exports.generateOverrideWarning = exports.generateOverrideError = exports.wrapContextHandler = exports.wrapInTryCatch = exports.generateId = void 0;
|
|
4
|
-
|
|
5
|
-
exports.
|
|
4
|
+
const generateId = () => `${Math.random()}${Date.now()}`;
|
|
5
|
+
exports.generateId = generateId;
|
|
6
|
+
const wrapInTryCatch = (f, prefix) => (...args) => {
|
|
6
7
|
try {
|
|
7
8
|
return f(...args);
|
|
8
9
|
}
|
|
@@ -10,7 +11,8 @@ exports.wrapInTryCatch = (f, prefix) => (...args) => {
|
|
|
10
11
|
throw new Error((prefix || '') + e);
|
|
11
12
|
}
|
|
12
13
|
};
|
|
13
|
-
exports.
|
|
14
|
+
exports.wrapInTryCatch = wrapInTryCatch;
|
|
15
|
+
const wrapContextHandler = (handler, handlerId) => {
|
|
14
16
|
return async (context) => {
|
|
15
17
|
try {
|
|
16
18
|
await handler(context);
|
|
@@ -21,28 +23,31 @@ exports.wrapContextHandler = (handler, handlerId) => {
|
|
|
21
23
|
}
|
|
22
24
|
};
|
|
23
25
|
};
|
|
24
|
-
exports.
|
|
26
|
+
exports.wrapContextHandler = wrapContextHandler;
|
|
27
|
+
const generateOverrideError = (clientApi, brokerApi) => {
|
|
25
28
|
return `You have tried to to use ${clientApi} but ${brokerApi} has not been overridden in the Interop Broker. Please override this function. Refer to our documentation for more info.`;
|
|
26
29
|
};
|
|
27
|
-
exports.
|
|
30
|
+
exports.generateOverrideError = generateOverrideError;
|
|
31
|
+
const generateOverrideWarning = (fdc3ClientApi, brokerApi, identity, interopClientApi) => {
|
|
28
32
|
const { uuid, name } = identity;
|
|
29
33
|
const message = interopClientApi
|
|
30
34
|
? `Entity with identity: ${uuid}/${name} has called ${interopClientApi} or ${fdc3ClientApi} but ${brokerApi} has not been overridden.`
|
|
31
35
|
: `Entity with identity: ${uuid}/${name} has called ${fdc3ClientApi} but ${brokerApi} has not been overridden.`;
|
|
32
36
|
return message;
|
|
33
37
|
};
|
|
38
|
+
exports.generateOverrideWarning = generateOverrideWarning;
|
|
34
39
|
exports.BROKER_ERRORS = {
|
|
35
|
-
fireIntent: exports.generateOverrideError('fireIntent', 'handleFiredIntent'),
|
|
36
|
-
fireIntentForContext: exports.generateOverrideError('fireIntentForContext', 'handleFiredIntentForContext'),
|
|
37
|
-
getInfoForIntent: exports.generateOverrideError('getInfoForIntent', 'handleInfoForIntent'),
|
|
38
|
-
getInfoForIntentsByContext: exports.generateOverrideError('getInfoForIntentsByContext', 'handleInfoForIntentsByContext'),
|
|
40
|
+
fireIntent: (0, exports.generateOverrideError)('fireIntent', 'handleFiredIntent'),
|
|
41
|
+
fireIntentForContext: (0, exports.generateOverrideError)('fireIntentForContext', 'handleFiredIntentForContext'),
|
|
42
|
+
getInfoForIntent: (0, exports.generateOverrideError)('getInfoForIntent', 'handleInfoForIntent'),
|
|
43
|
+
getInfoForIntentsByContext: (0, exports.generateOverrideError)('getInfoForIntentsByContext', 'handleInfoForIntentsByContext'),
|
|
39
44
|
joinSessionContextGroupWithJoinContextGroup: 'The Context Group you have tried to join is a Session Context Group. Custom Context Groups can only be defined by the Interop Broker through code or manifest configuration. Please use joinSessionContextGroup.',
|
|
40
|
-
fdc3Open: exports.generateOverrideError('fdc3.open', 'fdc3HandleOpen'),
|
|
41
|
-
fdc3FindInstances: exports.generateOverrideError('fdc3.findInstances', 'fdc3HandleFindInstances'),
|
|
42
|
-
fdc3GetAppMetadata: exports.generateOverrideError('fdc3.getAppMetadata', 'fdc3HandleGetAppMetadata'),
|
|
43
|
-
fdc3GetInfo: exports.generateOverrideError('fdc3.getInfo', 'fdc3HandleGetInfo')
|
|
45
|
+
fdc3Open: (0, exports.generateOverrideError)('fdc3.open', 'fdc3HandleOpen'),
|
|
46
|
+
fdc3FindInstances: (0, exports.generateOverrideError)('fdc3.findInstances', 'fdc3HandleFindInstances'),
|
|
47
|
+
fdc3GetAppMetadata: (0, exports.generateOverrideError)('fdc3.getAppMetadata', 'fdc3HandleGetAppMetadata'),
|
|
48
|
+
fdc3GetInfo: (0, exports.generateOverrideError)('fdc3.getInfo', 'fdc3HandleGetInfo')
|
|
44
49
|
};
|
|
45
|
-
|
|
50
|
+
const wrapIntentHandler = (handler, handlerId) => {
|
|
46
51
|
return async (intent) => {
|
|
47
52
|
try {
|
|
48
53
|
return handler(intent);
|
|
@@ -53,3 +58,4 @@ exports.wrapIntentHandler = (handler, handlerId) => {
|
|
|
53
58
|
}
|
|
54
59
|
};
|
|
55
60
|
};
|
|
61
|
+
exports.wrapIntentHandler = wrapIntentHandler;
|