@webex/internal-plugin-board 2.59.3-next.1 → 2.59.4-next.1

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/src/realtime.js CHANGED
@@ -1,252 +1,252 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- import uuid from 'uuid';
6
- import {tap} from '@webex/common';
7
- import {WebexPlugin} from '@webex/webex-core';
8
-
9
- import RealtimeChannelCollection from './realtime-channel-collection';
10
-
11
- /**
12
- * @class
13
- * @extends {Mercury}
14
- * @memberof Board
15
- */
16
- const RealtimeService = WebexPlugin.extend({
17
- namespace: 'Board',
18
-
19
- collections: {
20
- realtimeChannels: RealtimeChannelCollection,
21
- },
22
-
23
- /**
24
- * Sends the message via the socket. Assumes that the message is already properly formatted
25
- * @memberof Board.RealtimeService
26
- * @param {Board~Channel} channel
27
- * @param {string} message Contains the un-encrypted message to send.
28
- * @returns {Promise<Board~Content>}
29
- */
30
- publish(channel, message) {
31
- let encryptionPromise;
32
- let contentType = 'STRING';
33
-
34
- if (message.payload.file) {
35
- contentType = 'FILE';
36
- encryptionPromise = this.webex.internal.board.encryptSingleFileContent(
37
- channel.defaultEncryptionKeyUrl,
38
- message.payload
39
- );
40
- } else {
41
- encryptionPromise = this.webex.internal.board.encryptSingleContent(
42
- channel.defaultEncryptionKeyUrl,
43
- message.payload
44
- );
45
- }
46
-
47
- return encryptionPromise.then((encryptedPayloadAndKeyUrl) =>
48
- this.publishEncrypted(channel, encryptedPayloadAndKeyUrl, contentType)
49
- );
50
- },
51
-
52
- /**
53
- * Sends the message via the socket. The message should already have been
54
- * encrypted
55
- * @memberof Board.RealtimeService
56
- * @param {Board~Channel} channel
57
- * @param {object} encryptedPayloadAndKeyUrl
58
- * @param {string} contentType - provides hint for decryption. Defaults to
59
- * `STRING`, and could also be `FILE`
60
- * @returns {Promise<Board~Content>}
61
- */
62
- publishEncrypted(channel, encryptedPayloadAndKeyUrl, contentType) {
63
- const realtimeChannel = this.realtimeChannels.get(channel.channelId);
64
-
65
- if (!realtimeChannel) {
66
- return Promise.reject(new Error('Realtime Channel not found'));
67
- }
68
-
69
- const data = {
70
- id: uuid.v4(),
71
- type: 'publishRequest',
72
- recipients: [
73
- {
74
- alertType: 'none',
75
- route: realtimeChannel.binding,
76
- headers: {},
77
- },
78
- ],
79
- data: {
80
- eventType: 'board.activity',
81
- contentType,
82
- payload: encryptedPayloadAndKeyUrl.payload,
83
- envelope: {
84
- encryptionKeyUrl: encryptedPayloadAndKeyUrl.encryptionKeyUrl,
85
- channelId: channel.channelId,
86
- },
87
- },
88
- };
89
-
90
- // provide a hint for decryption
91
- if (contentType === 'FILE') {
92
- data.data.payload = {
93
- file: encryptedPayloadAndKeyUrl.file,
94
- payload: encryptedPayloadAndKeyUrl.payload,
95
- };
96
- }
97
-
98
- return realtimeChannel.send(data);
99
- },
100
-
101
- createRealtimeChannel(channel) {
102
- const requestBindings = [this._boardChannelIdToMercuryBinding(channel.channelId)];
103
- const bindingObj = {bindings: requestBindings};
104
-
105
- return this.webex.internal.board.register(bindingObj).then(({webSocketUrl, bindings}) => {
106
- this.realtimeChannels.add({
107
- channelId: channel.channelId,
108
- socketUrl: webSocketUrl,
109
- binding: bindings[0],
110
- });
111
-
112
- return this.realtimeChannels.get(channel.channelId);
113
- });
114
- },
115
-
116
- /**
117
- * Open new mercury connection
118
- * @memberof Board.RealtimeService
119
- * @param {Board~Channel} channel
120
- * @returns {Promise}
121
- */
122
- connectByOpenNewMercuryConnection(channel) {
123
- let promise = Promise.resolve();
124
- let realtimeChannel = this.realtimeChannels.get(channel.channelId);
125
-
126
- if (!realtimeChannel) {
127
- this.logger.info('board realtime: realtime channel not found, creating new channel');
128
- promise = this.createRealtimeChannel(channel).then((rc) => {
129
- realtimeChannel = rc;
130
- this.logger.info('board realtime: realtime channel created');
131
-
132
- return realtimeChannel;
133
- });
134
- }
135
-
136
- return promise.then(() => realtimeChannel.connect(realtimeChannel.socketUrl));
137
- },
138
-
139
- /**
140
- * Disconnect connection
141
- * @memberof Board.RealtimeService
142
- * @param {Board~Channel} channel
143
- * @returns {Promise}
144
- */
145
- disconnectMercuryConnection(channel) {
146
- const realtimeChannel = this.realtimeChannels.get(channel.channelId);
147
-
148
- if (!realtimeChannel) {
149
- return Promise.reject(new Error('Realtime Channel not found!'));
150
- }
151
-
152
- return (
153
- realtimeChannel
154
- .disconnect()
155
- // even if we can't remove the channels from the collection, we can still
156
- // continue on execution
157
- .then(tap(() => this.realtimeChannels.remove(channel.channelId)))
158
- );
159
- },
160
-
161
- /**
162
- * Ensure board channelId is compatible with mercury bindings by replacing
163
- * '-' with '.' and '_' with '#'
164
- * @memberof Board.BoardService
165
- * @param {String} channelId channel.channelId
166
- * @returns {String} mercury-binding compatible string
167
- */
168
- _boardChannelIdToMercuryBinding(channelId) {
169
- // make channelId mercury compatible replace `-` with `.` and `_` with `#`
170
- return this.config.mercuryBindingPrefix + channelId.replace(/-/g, '.').replace(/_/g, '#');
171
- },
172
-
173
- /**
174
- * Connect and use an exisiting mercury connection
175
- * @memberof Board.RealtimeService
176
- * @param {Board~Channel} channel
177
- * @returns {Promise<Board~Registration>}
178
- */
179
- connectToSharedMercury(channel) {
180
- return this.webex.internal.board.registerToShareMercury(channel).then((res) => {
181
- this.realtimeChannels.add({
182
- channelId: channel.channelId,
183
- binding: res.binding,
184
- socketUrl: res.webSocketUrl,
185
- });
186
-
187
- const realtimeChannel = this.realtimeChannels.get(channel.channelId);
188
-
189
- if (!res.sharedWebSocket) {
190
- return realtimeChannel.connect(realtimeChannel.socketUrl).then(() => res);
191
- }
192
-
193
- realtimeChannel.isSharingMercury = true;
194
- realtimeChannel.socket = this.webex.internal.mercury.socket;
195
- // refresh socket reference when mercury is reconnected
196
- this.webex.internal.mercury.off('online', this.refreshMercurySocketReference, this);
197
- this.webex.internal.mercury.on('online', this.refreshMercurySocketReference, this);
198
-
199
- // make sure there's only one handler
200
- this.webex.internal.mercury.off(
201
- 'event:board.activity',
202
- this.handleBoardActivityMessages,
203
- this
204
- );
205
- this.webex.internal.mercury.on(
206
- 'event:board.activity',
207
- this.handleBoardActivityMessages,
208
- this
209
- );
210
-
211
- return res;
212
- });
213
- },
214
-
215
- handleBoardActivityMessages(event) {
216
- const realtimeChannel = this.realtimeChannels.get(event.data.envelope.channelId);
217
-
218
- if (realtimeChannel) {
219
- realtimeChannel._emit('event:board.activity', event);
220
- }
221
- },
222
-
223
- refreshMercurySocketReference() {
224
- this.realtimeChannels.forEach((realtimeChannel) => {
225
- realtimeChannel.socket = this.webex.internal.mercury.socket;
226
- });
227
- },
228
-
229
- /**
230
- * Remove board binding from existing mercury connection
231
- * @memberof Board.RealtimeService
232
- * @param {Board~Channel} channel
233
- * @returns {Promise<Board~Registration>}
234
- */
235
- disconnectFromSharedMercury(channel) {
236
- const realtimeChannel = this.realtimeChannels.get(channel.channelId);
237
-
238
- if (!realtimeChannel.isSharingMercury && realtimeChannel.socket && realtimeChannel.connected) {
239
- return this.disconnectMercuryConnection(channel);
240
- }
241
-
242
- return (
243
- this.webex.internal.board
244
- .unregisterFromSharedMercury(channel, realtimeChannel.binding)
245
- // tap suppress errors but we can still go on if the channel can't be
246
- // removed from the collection
247
- .then(tap(() => this.realtimeChannels.remove(channel.channelId)))
248
- );
249
- },
250
- });
251
-
252
- export default RealtimeService;
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import uuid from 'uuid';
6
+ import {tap} from '@webex/common';
7
+ import {WebexPlugin} from '@webex/webex-core';
8
+
9
+ import RealtimeChannelCollection from './realtime-channel-collection';
10
+
11
+ /**
12
+ * @class
13
+ * @extends {Mercury}
14
+ * @memberof Board
15
+ */
16
+ const RealtimeService = WebexPlugin.extend({
17
+ namespace: 'Board',
18
+
19
+ collections: {
20
+ realtimeChannels: RealtimeChannelCollection,
21
+ },
22
+
23
+ /**
24
+ * Sends the message via the socket. Assumes that the message is already properly formatted
25
+ * @memberof Board.RealtimeService
26
+ * @param {Board~Channel} channel
27
+ * @param {string} message Contains the un-encrypted message to send.
28
+ * @returns {Promise<Board~Content>}
29
+ */
30
+ publish(channel, message) {
31
+ let encryptionPromise;
32
+ let contentType = 'STRING';
33
+
34
+ if (message.payload.file) {
35
+ contentType = 'FILE';
36
+ encryptionPromise = this.webex.internal.board.encryptSingleFileContent(
37
+ channel.defaultEncryptionKeyUrl,
38
+ message.payload
39
+ );
40
+ } else {
41
+ encryptionPromise = this.webex.internal.board.encryptSingleContent(
42
+ channel.defaultEncryptionKeyUrl,
43
+ message.payload
44
+ );
45
+ }
46
+
47
+ return encryptionPromise.then((encryptedPayloadAndKeyUrl) =>
48
+ this.publishEncrypted(channel, encryptedPayloadAndKeyUrl, contentType)
49
+ );
50
+ },
51
+
52
+ /**
53
+ * Sends the message via the socket. The message should already have been
54
+ * encrypted
55
+ * @memberof Board.RealtimeService
56
+ * @param {Board~Channel} channel
57
+ * @param {object} encryptedPayloadAndKeyUrl
58
+ * @param {string} contentType - provides hint for decryption. Defaults to
59
+ * `STRING`, and could also be `FILE`
60
+ * @returns {Promise<Board~Content>}
61
+ */
62
+ publishEncrypted(channel, encryptedPayloadAndKeyUrl, contentType) {
63
+ const realtimeChannel = this.realtimeChannels.get(channel.channelId);
64
+
65
+ if (!realtimeChannel) {
66
+ return Promise.reject(new Error('Realtime Channel not found'));
67
+ }
68
+
69
+ const data = {
70
+ id: uuid.v4(),
71
+ type: 'publishRequest',
72
+ recipients: [
73
+ {
74
+ alertType: 'none',
75
+ route: realtimeChannel.binding,
76
+ headers: {},
77
+ },
78
+ ],
79
+ data: {
80
+ eventType: 'board.activity',
81
+ contentType,
82
+ payload: encryptedPayloadAndKeyUrl.payload,
83
+ envelope: {
84
+ encryptionKeyUrl: encryptedPayloadAndKeyUrl.encryptionKeyUrl,
85
+ channelId: channel.channelId,
86
+ },
87
+ },
88
+ };
89
+
90
+ // provide a hint for decryption
91
+ if (contentType === 'FILE') {
92
+ data.data.payload = {
93
+ file: encryptedPayloadAndKeyUrl.file,
94
+ payload: encryptedPayloadAndKeyUrl.payload,
95
+ };
96
+ }
97
+
98
+ return realtimeChannel.send(data);
99
+ },
100
+
101
+ createRealtimeChannel(channel) {
102
+ const requestBindings = [this._boardChannelIdToMercuryBinding(channel.channelId)];
103
+ const bindingObj = {bindings: requestBindings};
104
+
105
+ return this.webex.internal.board.register(bindingObj).then(({webSocketUrl, bindings}) => {
106
+ this.realtimeChannels.add({
107
+ channelId: channel.channelId,
108
+ socketUrl: webSocketUrl,
109
+ binding: bindings[0],
110
+ });
111
+
112
+ return this.realtimeChannels.get(channel.channelId);
113
+ });
114
+ },
115
+
116
+ /**
117
+ * Open new mercury connection
118
+ * @memberof Board.RealtimeService
119
+ * @param {Board~Channel} channel
120
+ * @returns {Promise}
121
+ */
122
+ connectByOpenNewMercuryConnection(channel) {
123
+ let promise = Promise.resolve();
124
+ let realtimeChannel = this.realtimeChannels.get(channel.channelId);
125
+
126
+ if (!realtimeChannel) {
127
+ this.logger.info('board realtime: realtime channel not found, creating new channel');
128
+ promise = this.createRealtimeChannel(channel).then((rc) => {
129
+ realtimeChannel = rc;
130
+ this.logger.info('board realtime: realtime channel created');
131
+
132
+ return realtimeChannel;
133
+ });
134
+ }
135
+
136
+ return promise.then(() => realtimeChannel.connect(realtimeChannel.socketUrl));
137
+ },
138
+
139
+ /**
140
+ * Disconnect connection
141
+ * @memberof Board.RealtimeService
142
+ * @param {Board~Channel} channel
143
+ * @returns {Promise}
144
+ */
145
+ disconnectMercuryConnection(channel) {
146
+ const realtimeChannel = this.realtimeChannels.get(channel.channelId);
147
+
148
+ if (!realtimeChannel) {
149
+ return Promise.reject(new Error('Realtime Channel not found!'));
150
+ }
151
+
152
+ return (
153
+ realtimeChannel
154
+ .disconnect()
155
+ // even if we can't remove the channels from the collection, we can still
156
+ // continue on execution
157
+ .then(tap(() => this.realtimeChannels.remove(channel.channelId)))
158
+ );
159
+ },
160
+
161
+ /**
162
+ * Ensure board channelId is compatible with mercury bindings by replacing
163
+ * '-' with '.' and '_' with '#'
164
+ * @memberof Board.BoardService
165
+ * @param {String} channelId channel.channelId
166
+ * @returns {String} mercury-binding compatible string
167
+ */
168
+ _boardChannelIdToMercuryBinding(channelId) {
169
+ // make channelId mercury compatible replace `-` with `.` and `_` with `#`
170
+ return this.config.mercuryBindingPrefix + channelId.replace(/-/g, '.').replace(/_/g, '#');
171
+ },
172
+
173
+ /**
174
+ * Connect and use an exisiting mercury connection
175
+ * @memberof Board.RealtimeService
176
+ * @param {Board~Channel} channel
177
+ * @returns {Promise<Board~Registration>}
178
+ */
179
+ connectToSharedMercury(channel) {
180
+ return this.webex.internal.board.registerToShareMercury(channel).then((res) => {
181
+ this.realtimeChannels.add({
182
+ channelId: channel.channelId,
183
+ binding: res.binding,
184
+ socketUrl: res.webSocketUrl,
185
+ });
186
+
187
+ const realtimeChannel = this.realtimeChannels.get(channel.channelId);
188
+
189
+ if (!res.sharedWebSocket) {
190
+ return realtimeChannel.connect(realtimeChannel.socketUrl).then(() => res);
191
+ }
192
+
193
+ realtimeChannel.isSharingMercury = true;
194
+ realtimeChannel.socket = this.webex.internal.mercury.socket;
195
+ // refresh socket reference when mercury is reconnected
196
+ this.webex.internal.mercury.off('online', this.refreshMercurySocketReference, this);
197
+ this.webex.internal.mercury.on('online', this.refreshMercurySocketReference, this);
198
+
199
+ // make sure there's only one handler
200
+ this.webex.internal.mercury.off(
201
+ 'event:board.activity',
202
+ this.handleBoardActivityMessages,
203
+ this
204
+ );
205
+ this.webex.internal.mercury.on(
206
+ 'event:board.activity',
207
+ this.handleBoardActivityMessages,
208
+ this
209
+ );
210
+
211
+ return res;
212
+ });
213
+ },
214
+
215
+ handleBoardActivityMessages(event) {
216
+ const realtimeChannel = this.realtimeChannels.get(event.data.envelope.channelId);
217
+
218
+ if (realtimeChannel) {
219
+ realtimeChannel._emit('event:board.activity', event);
220
+ }
221
+ },
222
+
223
+ refreshMercurySocketReference() {
224
+ this.realtimeChannels.forEach((realtimeChannel) => {
225
+ realtimeChannel.socket = this.webex.internal.mercury.socket;
226
+ });
227
+ },
228
+
229
+ /**
230
+ * Remove board binding from existing mercury connection
231
+ * @memberof Board.RealtimeService
232
+ * @param {Board~Channel} channel
233
+ * @returns {Promise<Board~Registration>}
234
+ */
235
+ disconnectFromSharedMercury(channel) {
236
+ const realtimeChannel = this.realtimeChannels.get(channel.channelId);
237
+
238
+ if (!realtimeChannel.isSharingMercury && realtimeChannel.socket && realtimeChannel.connected) {
239
+ return this.disconnectMercuryConnection(channel);
240
+ }
241
+
242
+ return (
243
+ this.webex.internal.board
244
+ .unregisterFromSharedMercury(channel, realtimeChannel.binding)
245
+ // tap suppress errors but we can still go on if the channel can't be
246
+ // removed from the collection
247
+ .then(tap(() => this.realtimeChannels.remove(channel.channelId)))
248
+ );
249
+ },
250
+ });
251
+
252
+ export default RealtimeService;