@atlaskit/collab-provider 8.8.2 → 8.9.0
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/CHANGELOG.md +15 -0
- package/dist/cjs/analytics/analytics-helper.js +21 -12
- package/dist/cjs/channel.js +5 -3
- package/dist/cjs/document/document-service.js +1 -1
- package/dist/cjs/errors/error-code-mapper.js +9 -2
- package/dist/cjs/namespace/namespace-service.js +77 -0
- package/dist/cjs/participants/participants-helper.js +2 -0
- package/dist/cjs/participants/participants-service.js +94 -30
- package/dist/cjs/provider/index.js +91 -173
- package/dist/cjs/version-wrapper.js +1 -1
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/analytics/analytics-helper.js +21 -12
- package/dist/es2019/channel.js +5 -3
- package/dist/es2019/document/document-service.js +1 -1
- package/dist/es2019/errors/error-code-mapper.js +9 -2
- package/dist/es2019/namespace/namespace-service.js +48 -0
- package/dist/es2019/participants/participants-helper.js +2 -0
- package/dist/es2019/participants/participants-service.js +88 -30
- package/dist/es2019/provider/index.js +82 -145
- package/dist/es2019/version-wrapper.js +1 -1
- package/dist/es2019/version.json +1 -1
- package/dist/esm/analytics/analytics-helper.js +21 -12
- package/dist/esm/channel.js +5 -3
- package/dist/esm/document/document-service.js +1 -1
- package/dist/esm/errors/error-code-mapper.js +9 -2
- package/dist/esm/namespace/namespace-service.js +69 -0
- package/dist/esm/participants/participants-helper.js +2 -0
- package/dist/esm/participants/participants-service.js +94 -30
- package/dist/esm/provider/index.js +91 -173
- package/dist/esm/version-wrapper.js +1 -1
- package/dist/esm/version.json +1 -1
- package/dist/types/namespace/namespace-service.d.ts +14 -0
- package/dist/types/participants/participants-helper.d.ts +2 -4
- package/dist/types/participants/participants-service.d.ts +40 -16
- package/dist/types/provider/index.d.ts +20 -36
- package/dist/types/types.d.ts +1 -1
- package/dist/types-ts4.5/analytics/analytics-helper.d.ts +11 -0
- package/dist/types-ts4.5/analytics/performance.d.ts +15 -0
- package/dist/types-ts4.5/analytics/ufo.d.ts +3 -0
- package/dist/types-ts4.5/channel.d.ts +47 -0
- package/dist/types-ts4.5/config.d.ts +5 -0
- package/dist/types-ts4.5/connectivity/network.d.ts +17 -0
- package/dist/types-ts4.5/connectivity/reconnect-helper.d.ts +8 -0
- package/dist/types-ts4.5/connectivity/singleton.d.ts +3 -0
- package/dist/types-ts4.5/disconnected-reason-mapper.d.ts +16 -0
- package/dist/types-ts4.5/document/catchup.d.ts +9 -0
- package/dist/types-ts4.5/document/document-service.d.ts +86 -0
- package/dist/types-ts4.5/document/step-queue-state.d.ts +16 -0
- package/dist/types-ts4.5/emitter.d.ts +19 -0
- package/dist/types-ts4.5/errors/error-code-mapper.d.ts +2 -0
- package/dist/types-ts4.5/errors/error-types.d.ts +443 -0
- package/dist/types-ts4.5/feature-flags/__test__/index.unit.d.ts +1 -0
- package/dist/types-ts4.5/feature-flags/index.d.ts +9 -0
- package/dist/types-ts4.5/feature-flags/types.d.ts +13 -0
- package/dist/types-ts4.5/helpers/const.d.ts +183 -0
- package/dist/types-ts4.5/helpers/utils.d.ts +5 -0
- package/dist/types-ts4.5/index.d.ts +4 -0
- package/dist/types-ts4.5/metadata/metadata-service.d.ts +25 -0
- package/dist/types-ts4.5/namespace/namespace-service.d.ts +14 -0
- package/dist/types-ts4.5/participants/participants-helper.d.ts +12 -0
- package/dist/types-ts4.5/participants/participants-service.d.ts +94 -0
- package/dist/types-ts4.5/participants/participants-state.d.ts +13 -0
- package/dist/types-ts4.5/participants/telepointers-helper.d.ts +4 -0
- package/dist/types-ts4.5/provider/commit-step.d.ts +25 -0
- package/dist/types-ts4.5/provider/index.d.ts +146 -0
- package/dist/types-ts4.5/socket-io-provider.d.ts +5 -0
- package/dist/types-ts4.5/types.d.ts +265 -0
- package/dist/types-ts4.5/version-wrapper.d.ts +3 -0
- package/package.json +3 -3
- package/report.api.md +4 -2
|
@@ -4,16 +4,27 @@ import { EVENT_ACTION, EVENT_STATUS } from '../helpers/const';
|
|
|
4
4
|
import { telepointerFromStep } from './telepointers-helper';
|
|
5
5
|
import { createParticipantFromPayload as enrichParticipant, PARTICIPANT_UPDATE_INTERVAL } from './participants-helper';
|
|
6
6
|
import { ParticipantsState } from './participants-state';
|
|
7
|
+
import { createLogger } from '../helpers/utils';
|
|
8
|
+
const logger = createLogger('PresenceService', 'pink');
|
|
9
|
+
const SEND_PRESENCE_INTERVAL = 150 * 1000; // 150 seconds
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This service is responsible for handling presence and participant events, as well as sending them on to the editor or NCS.
|
|
13
|
+
* @param analyticsHelper Analytics helper instance
|
|
14
|
+
* @param participantsState Starts with no participants, only add this when testing
|
|
15
|
+
* @param emit Emit from the Provider class (to the editor)
|
|
16
|
+
* @param getUser Callback to get user data from the editor
|
|
17
|
+
* @param channelBroadcast Broadcast from the Channel class (to NCS)
|
|
18
|
+
* @param sendPresenceJoined Callback to Channel class
|
|
19
|
+
*/
|
|
7
20
|
export class ParticipantsService {
|
|
8
|
-
constructor(analyticsHelper, participantsState = new ParticipantsState()) {
|
|
21
|
+
constructor(analyticsHelper, participantsState = new ParticipantsState(), emit, getUser, channelBroadcast, sendPresenceJoined) {
|
|
9
22
|
/**
|
|
10
23
|
* Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
|
|
11
24
|
* @param payload Payload from incoming socket event
|
|
12
|
-
* @param getUser Function to get user data from confluence
|
|
13
|
-
* @param emit Function to execute emit from provider socket
|
|
14
25
|
* @returns Awaitable Promise, due to getUser
|
|
15
26
|
*/
|
|
16
|
-
_defineProperty(this, "
|
|
27
|
+
_defineProperty(this, "onParticipantUpdated", async payload => {
|
|
17
28
|
const {
|
|
18
29
|
userId
|
|
19
30
|
} = payload;
|
|
@@ -30,11 +41,11 @@ export class ParticipantsService {
|
|
|
30
41
|
{
|
|
31
42
|
...payload,
|
|
32
43
|
userId
|
|
33
|
-
}, getUser);
|
|
44
|
+
}, this.getUser);
|
|
34
45
|
} catch (error) {
|
|
35
46
|
var _this$analyticsHelper;
|
|
36
47
|
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
37
|
-
(_this$analyticsHelper = this.analyticsHelper) === null || _this$analyticsHelper === void 0 ? void 0 : _this$analyticsHelper.sendErrorEvent(error, 'enriching participant');
|
|
48
|
+
(_this$analyticsHelper = this.analyticsHelper) === null || _this$analyticsHelper === void 0 ? void 0 : _this$analyticsHelper.sendErrorEvent(error, 'Error while enriching participant');
|
|
38
49
|
}
|
|
39
50
|
if (!participant) {
|
|
40
51
|
return;
|
|
@@ -46,28 +57,27 @@ export class ParticipantsService {
|
|
|
46
57
|
}
|
|
47
58
|
this.emitPresence({
|
|
48
59
|
joined: [participant]
|
|
49
|
-
},
|
|
60
|
+
}, 'handling participant updated event');
|
|
50
61
|
});
|
|
51
62
|
/**
|
|
52
63
|
* Called when a participant leaves the session.
|
|
53
|
-
*
|
|
54
64
|
* We emit the `presence` event to update the active avatars in the editor.
|
|
55
65
|
*/
|
|
56
|
-
_defineProperty(this, "
|
|
66
|
+
_defineProperty(this, "onParticipantLeft", ({
|
|
57
67
|
sessionId
|
|
58
|
-
}
|
|
68
|
+
}) => {
|
|
59
69
|
this.participantsState.removeBySessionId(sessionId);
|
|
60
70
|
this.emitPresence({
|
|
61
71
|
left: [{
|
|
62
72
|
sessionId
|
|
63
73
|
}]
|
|
64
|
-
},
|
|
74
|
+
}, 'participant leaving');
|
|
65
75
|
});
|
|
66
|
-
_defineProperty(this, "disconnect", (reason, sessionId
|
|
76
|
+
_defineProperty(this, "disconnect", (reason, sessionId) => {
|
|
67
77
|
const left = this.participantsState.getParticipants();
|
|
68
78
|
this.participantsState.clear();
|
|
69
79
|
try {
|
|
70
|
-
emit('disconnected', {
|
|
80
|
+
this.emit('disconnected', {
|
|
71
81
|
reason: disconnectedReasonMapper(reason),
|
|
72
82
|
sid: sessionId
|
|
73
83
|
});
|
|
@@ -79,7 +89,7 @@ export class ParticipantsService {
|
|
|
79
89
|
if (left.length) {
|
|
80
90
|
this.emitPresence({
|
|
81
91
|
left
|
|
82
|
-
},
|
|
92
|
+
}, 'emitting presence update on disconnect');
|
|
83
93
|
}
|
|
84
94
|
});
|
|
85
95
|
/**
|
|
@@ -91,7 +101,7 @@ export class ParticipantsService {
|
|
|
91
101
|
* Called when we receive a telepointer update from another
|
|
92
102
|
* participant.
|
|
93
103
|
*/
|
|
94
|
-
_defineProperty(this, "
|
|
104
|
+
_defineProperty(this, "onParticipantTelepointer", (payload, thisSessionId) => {
|
|
95
105
|
const {
|
|
96
106
|
sessionId,
|
|
97
107
|
selection,
|
|
@@ -111,44 +121,43 @@ export class ParticipantsService {
|
|
|
111
121
|
type: 'telepointer',
|
|
112
122
|
selection,
|
|
113
123
|
sessionId
|
|
114
|
-
},
|
|
124
|
+
}, 'handling participant telepointer event');
|
|
115
125
|
});
|
|
116
126
|
/**
|
|
117
127
|
* Every 5 minutes (PARTICIPANT_UPDATE_INTERVAL), removes inactive participants and emits the update to other participants.
|
|
118
128
|
* Needs to be kicked off in the Provider.
|
|
119
129
|
* @param sessionId SessionId from provider's connection
|
|
120
|
-
* @param emit Function to execute emit from provider socket
|
|
121
130
|
*/
|
|
122
|
-
_defineProperty(this, "
|
|
131
|
+
_defineProperty(this, "startInactiveRemover", sessionId => {
|
|
123
132
|
clearTimeout(this.participantUpdateTimeout);
|
|
124
133
|
try {
|
|
125
|
-
this.filterInactive(sessionId
|
|
134
|
+
this.filterInactive(sessionId);
|
|
126
135
|
} catch (err) {
|
|
127
136
|
var _this$analyticsHelper3;
|
|
128
137
|
(_this$analyticsHelper3 = this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 ? void 0 : _this$analyticsHelper3.sendErrorEvent(err, 'Failed filtering inactive participants');
|
|
129
138
|
}
|
|
130
|
-
this.participantUpdateTimeout = window.setTimeout(() => this.
|
|
139
|
+
this.participantUpdateTimeout = window.setTimeout(() => this.startInactiveRemover(sessionId), PARTICIPANT_UPDATE_INTERVAL);
|
|
131
140
|
});
|
|
132
141
|
/**
|
|
133
142
|
* Keep list of participants up to date. Filter out inactive users etc.
|
|
134
143
|
*/
|
|
135
|
-
_defineProperty(this, "filterInactive",
|
|
144
|
+
_defineProperty(this, "filterInactive", sessionId => {
|
|
136
145
|
const now = Date.now();
|
|
137
146
|
const left = this.participantsState.getParticipants().filter(p => p.sessionId !== sessionId && now - p.lastActive > PARTICIPANT_UPDATE_INTERVAL);
|
|
138
147
|
left.forEach(p => this.participantsState.removeBySessionId(p.sessionId));
|
|
139
148
|
left.length && this.emitPresence({
|
|
140
149
|
left
|
|
141
|
-
},
|
|
150
|
+
}, 'filtering inactive participants');
|
|
142
151
|
});
|
|
143
152
|
/**
|
|
144
153
|
* Wrapper function to emit with error handling and analytics
|
|
145
154
|
* @param data Data to emit
|
|
146
155
|
* @param emit Emit function from Provider
|
|
147
156
|
*/
|
|
148
|
-
_defineProperty(this, "emitPresence", (data,
|
|
157
|
+
_defineProperty(this, "emitPresence", (data, errorMessage) => {
|
|
149
158
|
try {
|
|
150
159
|
var _this$analyticsHelper4;
|
|
151
|
-
emit('presence', data);
|
|
160
|
+
this.emit('presence', data);
|
|
152
161
|
(_this$analyticsHelper4 = this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 ? void 0 : _this$analyticsHelper4.sendActionEvent(EVENT_ACTION.UPDATE_PARTICIPANTS, EVENT_STATUS.SUCCESS, {
|
|
153
162
|
participants: this.participantsState.size()
|
|
154
163
|
});
|
|
@@ -163,9 +172,9 @@ export class ParticipantsService {
|
|
|
163
172
|
* @param data Data to emit
|
|
164
173
|
* @param emit Emit function from Provider
|
|
165
174
|
*/
|
|
166
|
-
_defineProperty(this, "emitTelepointer", (data,
|
|
175
|
+
_defineProperty(this, "emitTelepointer", (data, errorMessage) => {
|
|
167
176
|
try {
|
|
168
|
-
emit('telepointer', data);
|
|
177
|
+
this.emit('telepointer', data);
|
|
169
178
|
} catch (error) {
|
|
170
179
|
var _this$analyticsHelper6;
|
|
171
180
|
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
@@ -178,19 +187,68 @@ export class ParticipantsService {
|
|
|
178
187
|
_defineProperty(this, "clearTimers", () => {
|
|
179
188
|
clearTimeout(this.participantUpdateTimeout);
|
|
180
189
|
});
|
|
181
|
-
this
|
|
190
|
+
_defineProperty(this, "sendPresence", payload => {
|
|
191
|
+
try {
|
|
192
|
+
clearTimeout(this.presenceUpdateTimeout);
|
|
193
|
+
this.channelBroadcast('participant:updated', payload);
|
|
194
|
+
this.presenceUpdateTimeout = window.setTimeout(() => this.sendPresence(payload), SEND_PRESENCE_INTERVAL);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
var _this$analyticsHelper7;
|
|
197
|
+
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
198
|
+
(_this$analyticsHelper7 = this.analyticsHelper) === null || _this$analyticsHelper7 === void 0 ? void 0 : _this$analyticsHelper7.sendErrorEvent(error, 'Error while sending presence');
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
/**
|
|
202
|
+
* Called when a participant joins the session.
|
|
203
|
+
*
|
|
204
|
+
* We keep track of participants internally, and emit the `presence` event to update
|
|
205
|
+
* the active avatars in the editor.
|
|
206
|
+
* This method will be triggered from backend to notify all participants to exchange presence
|
|
207
|
+
*/
|
|
208
|
+
_defineProperty(this, "onPresenceJoined", payload => {
|
|
209
|
+
try {
|
|
210
|
+
logger('Participant joined with session: ', payload.sessionId);
|
|
211
|
+
// This expose existing users to the newly joined user
|
|
212
|
+
this.sendPresence(payload);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
var _this$analyticsHelper8;
|
|
215
|
+
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
216
|
+
(_this$analyticsHelper8 = this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 ? void 0 : _this$analyticsHelper8.sendErrorEvent(error, 'Error while joining presence');
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
/**
|
|
220
|
+
* Called when the current user joins the session.
|
|
221
|
+
*
|
|
222
|
+
* This will send both a 'presence' event and a 'participant:updated' event.
|
|
223
|
+
* This updates both the avatars and the participants list.
|
|
224
|
+
*/
|
|
225
|
+
_defineProperty(this, "onPresence", payload => {
|
|
226
|
+
try {
|
|
227
|
+
logger('onPresence userId: ', payload.userId);
|
|
228
|
+
this.sendPresence(payload);
|
|
229
|
+
this.sendPresenceJoined();
|
|
230
|
+
} catch (error) {
|
|
231
|
+
var _this$analyticsHelper9;
|
|
232
|
+
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
233
|
+
(_this$analyticsHelper9 = this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 ? void 0 : _this$analyticsHelper9.sendErrorEvent(error, 'Error while receiving presence');
|
|
234
|
+
}
|
|
235
|
+
});
|
|
182
236
|
this.analyticsHelper = analyticsHelper;
|
|
237
|
+
this.participantsState = participantsState;
|
|
238
|
+
this.emit = emit;
|
|
239
|
+
this.getUser = getUser;
|
|
240
|
+
this.channelBroadcast = channelBroadcast;
|
|
241
|
+
this.sendPresenceJoined = sendPresenceJoined;
|
|
183
242
|
}
|
|
184
243
|
/**
|
|
185
244
|
* Called on receiving steps, emits each step's telepointer
|
|
186
245
|
* @param steps Steps to extract telepointers from
|
|
187
|
-
* @param emit Provider emit function
|
|
188
246
|
*/
|
|
189
|
-
emitTelepointersFromSteps(steps
|
|
247
|
+
emitTelepointersFromSteps(steps) {
|
|
190
248
|
steps.forEach(step => {
|
|
191
249
|
const event = telepointerFromStep(this.participantsState.getParticipants(), step);
|
|
192
250
|
if (event) {
|
|
193
|
-
this.emitTelepointer(event,
|
|
251
|
+
this.emitTelepointer(event, 'emitting telepointers from steps');
|
|
194
252
|
}
|
|
195
253
|
});
|
|
196
254
|
}
|
|
@@ -4,14 +4,13 @@ import { Channel } from '../channel';
|
|
|
4
4
|
import { createLogger } from '../helpers/utils';
|
|
5
5
|
import AnalyticsHelper from '../analytics/analytics-helper';
|
|
6
6
|
import { telepointerCallback } from '../participants/telepointers-helper';
|
|
7
|
-
import { ParticipantsService } from '../participants/participants-service';
|
|
8
7
|
import { DestroyError, GetCurrentStateError, GetFinalAcknowledgedStateError, ProviderInitialisationError, SendTransactionError, SetEditorWidthError, SetMetadataError, SetTitleError, NCS_ERROR_CODE } from '../errors/error-types';
|
|
9
8
|
import { MetadataService } from '../metadata/metadata-service';
|
|
10
9
|
import { DocumentService } from '../document/document-service';
|
|
10
|
+
import { NamespaceService } from '../namespace/namespace-service';
|
|
11
|
+
import { ParticipantsService } from '../participants/participants-service';
|
|
11
12
|
import { errorCodeMapper } from '../errors/error-code-mapper';
|
|
12
13
|
const logger = createLogger('Provider', 'black');
|
|
13
|
-
const SEND_PRESENCE_INTERVAL = 150 * 1000; // 150 seconds
|
|
14
|
-
|
|
15
14
|
const OUT_OF_SYNC_PERIOD = 3 * 1000; // 3 seconds
|
|
16
15
|
|
|
17
16
|
export const MAX_STEP_REJECTED_ERROR = 15;
|
|
@@ -20,9 +19,24 @@ export class Provider extends Emitter {
|
|
|
20
19
|
super();
|
|
21
20
|
_defineProperty(this, "isChannelInitialized", false);
|
|
22
21
|
_defineProperty(this, "isProviderInitialized", false);
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
_defineProperty(this, "
|
|
22
|
+
// isPreinitializating acts as a feature flag to determine when the provider has been initialized early
|
|
23
|
+
// and also contains the initial draft
|
|
24
|
+
_defineProperty(this, "isPreinitializing", false);
|
|
25
|
+
/**
|
|
26
|
+
* Wrapper for this.emit, it binds scope for callbacks and waits for initialising of the editor before emitting events.
|
|
27
|
+
* Waiting for the collab provider to become connected to the editor ensures the editor doesn't miss any events.
|
|
28
|
+
* @param evt - Event name to emit to subscribers
|
|
29
|
+
* @param data - Event data to emit to subscribers
|
|
30
|
+
*/
|
|
31
|
+
_defineProperty(this, "emitCallback", (evt, data) => {
|
|
32
|
+
// When the provider is initialized early, we want the editor state promise to resolve before emitting events
|
|
33
|
+
// to ensure that it is ready to listen to the events fired by NCS
|
|
34
|
+
if (this.isPreinitializing) {
|
|
35
|
+
this.getStatePromise.then(() => this.emit(evt, data));
|
|
36
|
+
} else {
|
|
37
|
+
this.emit(evt, data);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
26
40
|
_defineProperty(this, "initializeChannel", () => {
|
|
27
41
|
this.emit('connecting', {
|
|
28
42
|
initial: true
|
|
@@ -33,7 +47,7 @@ export class Provider extends Emitter {
|
|
|
33
47
|
initialized
|
|
34
48
|
}) => {
|
|
35
49
|
this.sessionId = sid;
|
|
36
|
-
this.
|
|
50
|
+
this.emitCallback('connected', {
|
|
37
51
|
sid,
|
|
38
52
|
initial: !initialized
|
|
39
53
|
});
|
|
@@ -60,7 +74,7 @@ export class Provider extends Emitter {
|
|
|
60
74
|
Date.now() - this.disconnectedAt >= OUT_OF_SYNC_PERIOD) {
|
|
61
75
|
this.documentService.throttledCatchup();
|
|
62
76
|
}
|
|
63
|
-
this.startInactiveRemover();
|
|
77
|
+
this.participantsService.startInactiveRemover(this.sessionId);
|
|
64
78
|
this.disconnectedAt = undefined;
|
|
65
79
|
}).on('init', ({
|
|
66
80
|
doc,
|
|
@@ -74,7 +88,8 @@ export class Provider extends Emitter {
|
|
|
74
88
|
metadata
|
|
75
89
|
});
|
|
76
90
|
this.metadataService.updateMetadata(metadata);
|
|
77
|
-
|
|
91
|
+
this.isProviderInitialized = true;
|
|
92
|
+
}).on('restore', this.documentService.onRestore).on('steps:added', this.documentService.onStepsAdded).on('metadata:changed', this.metadataService.onMetadataChanged).on('participant:telepointer', payload => this.participantsService.onParticipantTelepointer(payload, this.sessionId)).on('presence:joined', this.participantsService.onPresenceJoined).on('presence', this.participantsService.onPresence).on('participant:left', this.participantsService.onParticipantLeft).on('participant:updated', this.participantsService.onParticipantUpdated).on('disconnect', this.onDisconnected.bind(this)).on('error', this.onErrorHandled).on('status', this.namespaceService.onNamespaceStatusChanged).connect(shouldInitialize);
|
|
78
93
|
});
|
|
79
94
|
/**
|
|
80
95
|
* @param {InternalError} error The error to handle
|
|
@@ -94,83 +109,16 @@ export class Provider extends Emitter {
|
|
|
94
109
|
if (mappedError) {
|
|
95
110
|
var _this$analyticsHelper2;
|
|
96
111
|
(_this$analyticsHelper2 = this.analyticsHelper) === null || _this$analyticsHelper2 === void 0 ? void 0 : _this$analyticsHelper2.sendErrorEvent(mappedError, 'Error emitted');
|
|
97
|
-
this.
|
|
112
|
+
this.emitCallback('error', mappedError);
|
|
98
113
|
}
|
|
99
114
|
}
|
|
100
115
|
});
|
|
101
|
-
_defineProperty(this, "sendPresence", () => {
|
|
102
|
-
try {
|
|
103
|
-
if (this.presenceUpdateTimeout) {
|
|
104
|
-
clearTimeout(this.presenceUpdateTimeout);
|
|
105
|
-
}
|
|
106
|
-
this.channel.broadcast('participant:updated', {
|
|
107
|
-
sessionId: this.sessionId,
|
|
108
|
-
userId: this.userId,
|
|
109
|
-
clientId: this.clientId
|
|
110
|
-
});
|
|
111
|
-
this.presenceUpdateTimeout = window.setTimeout(() => this.sendPresence(), SEND_PRESENCE_INTERVAL);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
var _this$analyticsHelper3;
|
|
114
|
-
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
115
|
-
(_this$analyticsHelper3 = this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 ? void 0 : _this$analyticsHelper3.sendErrorEvent(error, 'Error while sending presence');
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
/**
|
|
119
|
-
* Called when a participant joins the session.
|
|
120
|
-
*
|
|
121
|
-
* We keep track of participants internally in this class, and emit the `presence` event to update
|
|
122
|
-
* the active avatars in the editor.
|
|
123
|
-
* This method will be triggered from backend to notify all participants to exchange presence
|
|
124
|
-
*/
|
|
125
|
-
_defineProperty(this, "onPresenceJoined", ({
|
|
126
|
-
sessionId
|
|
127
|
-
}) => {
|
|
128
|
-
try {
|
|
129
|
-
logger('Participant joined with session: ', sessionId);
|
|
130
|
-
// This expose existing users to the newly joined user
|
|
131
|
-
this.sendPresence();
|
|
132
|
-
} catch (error) {
|
|
133
|
-
var _this$analyticsHelper4;
|
|
134
|
-
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
135
|
-
(_this$analyticsHelper4 = this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 ? void 0 : _this$analyticsHelper4.sendErrorEvent(error, 'Error while joining presence');
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
_defineProperty(this, "onPresence", ({
|
|
139
|
-
userId
|
|
140
|
-
}) => {
|
|
141
|
-
try {
|
|
142
|
-
logger('onPresence userId: ', userId);
|
|
143
|
-
this.userId = userId;
|
|
144
|
-
this.sendPresence();
|
|
145
|
-
this.channel.sendPresenceJoined();
|
|
146
|
-
} catch (error) {
|
|
147
|
-
var _this$analyticsHelper5;
|
|
148
|
-
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
149
|
-
(_this$analyticsHelper5 = this.analyticsHelper) === null || _this$analyticsHelper5 === void 0 ? void 0 : _this$analyticsHelper5.sendErrorEvent(error, 'Error while receiving presence');
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
/**
|
|
153
|
-
* Called when a participant leaves the session.
|
|
154
|
-
*
|
|
155
|
-
* We emit the `presence` event to update the active avatars in the editor.
|
|
156
|
-
*/
|
|
157
|
-
_defineProperty(this, "onParticipantLeft", data => this.participantsService.participantLeft(data, this.emitCallback));
|
|
158
|
-
_defineProperty(this, "startInactiveRemover", () => this.participantsService.removeInactiveParticipants(this.sessionId, this.emitCallback));
|
|
159
|
-
/**
|
|
160
|
-
* Called when we receive an update event from another participant.
|
|
161
|
-
*/
|
|
162
|
-
_defineProperty(this, "onParticipantUpdated", data => this.participantsService.updateParticipant(data, this.config.getUser, this.emitCallback));
|
|
163
|
-
/**
|
|
164
|
-
* Called when we receive a telepointer update from another
|
|
165
|
-
* participant.
|
|
166
|
-
*/
|
|
167
|
-
_defineProperty(this, "onParticipantTelepointer", data => this.participantsService.participantTelepointer(data, this.sessionId, this.config.getUser, this.emitCallback));
|
|
168
116
|
// Note: this gets triggered on page reload for Firefox (not other browsers) because of closeOnBeforeunload: false
|
|
169
117
|
_defineProperty(this, "onDisconnected", ({
|
|
170
118
|
reason
|
|
171
119
|
}) => {
|
|
172
120
|
this.disconnectedAt = Date.now();
|
|
173
|
-
this.participantsService.disconnect(reason, this.sessionId
|
|
121
|
+
this.participantsService.disconnect(reason, this.sessionId);
|
|
174
122
|
});
|
|
175
123
|
/**
|
|
176
124
|
* Returns the documents metadata
|
|
@@ -187,8 +135,8 @@ export class Provider extends Emitter {
|
|
|
187
135
|
try {
|
|
188
136
|
return this.documentService.getCurrentState();
|
|
189
137
|
} catch (error) {
|
|
190
|
-
var _this$
|
|
191
|
-
(_this$
|
|
138
|
+
var _this$analyticsHelper3;
|
|
139
|
+
(_this$analyticsHelper3 = this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 ? void 0 : _this$analyticsHelper3.sendErrorEvent(error, 'Error while returning ADF version of current draft document');
|
|
192
140
|
throw new GetCurrentStateError('Error while returning the current state of the draft document', error); // Reject the promise so the consumer can react to it failing
|
|
193
141
|
}
|
|
194
142
|
});
|
|
@@ -201,46 +149,14 @@ export class Provider extends Emitter {
|
|
|
201
149
|
try {
|
|
202
150
|
return this.documentService.getFinalAcknowledgedState();
|
|
203
151
|
} catch (error) {
|
|
204
|
-
var _this$
|
|
205
|
-
(_this$
|
|
152
|
+
var _this$analyticsHelper4;
|
|
153
|
+
(_this$analyticsHelper4 = this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 ? void 0 : _this$analyticsHelper4.sendErrorEvent(error, 'Error while returning ADF version of the final draft document');
|
|
206
154
|
throw new GetFinalAcknowledgedStateError('Error while returning the final acknowledged state of the draft document', error); // Reject the promise so the consumer can react to it failing
|
|
207
155
|
}
|
|
208
156
|
});
|
|
209
157
|
_defineProperty(this, "getUnconfirmedSteps", () => {
|
|
210
158
|
return this.documentService.getUnconfirmedSteps();
|
|
211
159
|
});
|
|
212
|
-
/**
|
|
213
|
-
* ESS-2916 namespace status event- lock/unlock
|
|
214
|
-
*/
|
|
215
|
-
_defineProperty(this, "onNamespaceStatusChanged", async data => {
|
|
216
|
-
const {
|
|
217
|
-
isLocked,
|
|
218
|
-
waitTimeInMs,
|
|
219
|
-
timestamp
|
|
220
|
-
} = data;
|
|
221
|
-
const start = Date.now();
|
|
222
|
-
logger(`Received a namespace status changed event `, {
|
|
223
|
-
data
|
|
224
|
-
});
|
|
225
|
-
if (isLocked && waitTimeInMs) {
|
|
226
|
-
this.isNamespaceLocked = true;
|
|
227
|
-
logger(`Received a namespace status change event `, {
|
|
228
|
-
isLocked
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
// To protect the collab editing process from locked out due to BE
|
|
232
|
-
setTimeout(() => {
|
|
233
|
-
logger(`The namespace lock has expired`, {
|
|
234
|
-
waitTime: Date.now() - start,
|
|
235
|
-
timestamp
|
|
236
|
-
});
|
|
237
|
-
this.isNamespaceLocked = false;
|
|
238
|
-
}, waitTimeInMs);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
this.isNamespaceLocked = false;
|
|
242
|
-
logger(`The page lock has expired`);
|
|
243
|
-
});
|
|
244
160
|
/**
|
|
245
161
|
* Used when the provider is disconnected or destroyed to prevent perpetual timers from continuously running
|
|
246
162
|
*/
|
|
@@ -254,9 +170,14 @@ export class Provider extends Emitter {
|
|
|
254
170
|
this.isChannelInitialized = false;
|
|
255
171
|
this.initialDraft = this.config.initialDraft;
|
|
256
172
|
this.isProviderInitialized = false;
|
|
257
|
-
this.
|
|
173
|
+
this.isPreinitializing = false;
|
|
174
|
+
this.participantsService = new ParticipantsService(this.analyticsHelper, undefined, this.emitCallback, this.config.getUser, this.channel.broadcast, this.channel.sendPresenceJoined);
|
|
258
175
|
this.metadataService = new MetadataService(this.emitCallback, this.channel.sendMetadata);
|
|
259
176
|
this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService);
|
|
177
|
+
this.getStatePromise = new Promise(resolve => {
|
|
178
|
+
this.getStatePromiseResolve = resolve;
|
|
179
|
+
});
|
|
180
|
+
this.namespaceService = new NamespaceService();
|
|
260
181
|
}
|
|
261
182
|
/**
|
|
262
183
|
* Initialisation logic, called by Jira with a dummy getState function, deprecated in favour of the setup method which allows more configuration
|
|
@@ -271,10 +192,15 @@ export class Provider extends Emitter {
|
|
|
271
192
|
}
|
|
272
193
|
|
|
273
194
|
/**
|
|
274
|
-
* Initialisation logic, called by the editor in the collab-edit plugin
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
195
|
+
* Initialisation logic, called by the editor in the collab-edit plugin.
|
|
196
|
+
*
|
|
197
|
+
* When getState is nullish and a initialDraft is provided the collab provider is in a state of pre-initialization,
|
|
198
|
+
* the provider starts to enable the connection to NCS, but the provider will not emit any events until this function
|
|
199
|
+
* is called again with a getState function, indicating that the editor is loaded and ready to receive the emits.
|
|
200
|
+
*
|
|
201
|
+
* @param {Object} options ...
|
|
202
|
+
* @param {Function} options.getState Function that returns the editor state, used to retrieve collab-edit properties and to interact with prosemirror-collab
|
|
203
|
+
* @param {SyncUpErrorFunction} options.onSyncUpError (Optional) Function that gets called when the sync of steps fails after retrying 30 times, used by Editor to log to analytics
|
|
278
204
|
* @throws {ProviderInitialisationError} Something went wrong during provider initialisation
|
|
279
205
|
*/
|
|
280
206
|
setup({
|
|
@@ -283,23 +209,34 @@ export class Provider extends Emitter {
|
|
|
283
209
|
}) {
|
|
284
210
|
this.checkForCookies();
|
|
285
211
|
try {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
212
|
+
// if setup is called with no state and the initial draft is already provided
|
|
213
|
+
// set a flag to mark early provider setup
|
|
214
|
+
if (!getState && this.initialDraft) {
|
|
215
|
+
this.isPreinitializing = true;
|
|
216
|
+
}
|
|
217
|
+
if (getState) {
|
|
218
|
+
// if provider has already been initialized earlier, resolve the state once it is available
|
|
219
|
+
if (this.isPreinitializing) {
|
|
220
|
+
this.getStatePromiseResolve();
|
|
221
|
+
}
|
|
222
|
+
const collabPlugin = getState().plugins.find(p => p.key === 'collab$');
|
|
223
|
+
if (collabPlugin === undefined) {
|
|
224
|
+
throw new ProviderInitialisationError('Collab provider attempted to initialise, but Editor state is missing collab plugin');
|
|
225
|
+
}
|
|
226
|
+
this.clientId = collabPlugin.spec.config.clientID;
|
|
227
|
+
this.documentService.setup({
|
|
228
|
+
getState,
|
|
229
|
+
onSyncUpError,
|
|
230
|
+
clientId: this.clientId
|
|
231
|
+
});
|
|
289
232
|
}
|
|
290
|
-
this.clientId = collabPlugin.spec.config.clientID;
|
|
291
|
-
this.documentService.setup({
|
|
292
|
-
getState,
|
|
293
|
-
onSyncUpError,
|
|
294
|
-
clientId: this.clientId
|
|
295
|
-
});
|
|
296
233
|
if (!this.isChannelInitialized) {
|
|
297
234
|
this.initializeChannel();
|
|
298
235
|
this.isChannelInitialized = true;
|
|
299
236
|
}
|
|
300
237
|
} catch (initError) {
|
|
301
|
-
var _this$
|
|
302
|
-
(_this$
|
|
238
|
+
var _this$analyticsHelper5;
|
|
239
|
+
(_this$analyticsHelper5 = this.analyticsHelper) === null || _this$analyticsHelper5 === void 0 ? void 0 : _this$analyticsHelper5.sendErrorEvent(initError, 'Error while initialising the provider');
|
|
303
240
|
// Throw error so consumers are aware the initialisation failed when initialising themselves
|
|
304
241
|
throw new ProviderInitialisationError('Provider initialisation error', initError);
|
|
305
242
|
}
|
|
@@ -307,9 +244,9 @@ export class Provider extends Emitter {
|
|
|
307
244
|
}
|
|
308
245
|
checkForCookies() {
|
|
309
246
|
if (!global.navigator.cookieEnabled) {
|
|
310
|
-
var _this$
|
|
247
|
+
var _this$analyticsHelper6;
|
|
311
248
|
const initError = new ProviderInitialisationError('Cookies are not enabled. Please enable cookies to use collaborative editing.');
|
|
312
|
-
(_this$
|
|
249
|
+
(_this$analyticsHelper6 = this.analyticsHelper) === null || _this$analyticsHelper6 === void 0 ? void 0 : _this$analyticsHelper6.sendErrorEvent(initError, 'Error while initialising the provider - cookies disabled');
|
|
313
250
|
throw new ProviderInitialisationError('Provider initialisation error - cookies disabled', initError);
|
|
314
251
|
}
|
|
315
252
|
}
|
|
@@ -324,14 +261,14 @@ export class Provider extends Emitter {
|
|
|
324
261
|
send(_tr, _oldState, newState) {
|
|
325
262
|
try {
|
|
326
263
|
// Don't send steps while the document is locked (eg. when restoring the document)
|
|
327
|
-
if (this.
|
|
264
|
+
if (this.namespaceService.getIsNamespaceLocked()) {
|
|
328
265
|
logger('The document is temporary locked');
|
|
329
266
|
return;
|
|
330
267
|
}
|
|
331
268
|
this.documentService.send(_tr, _oldState, newState);
|
|
332
269
|
} catch (error) {
|
|
333
|
-
var _this$
|
|
334
|
-
(_this$
|
|
270
|
+
var _this$analyticsHelper7;
|
|
271
|
+
(_this$analyticsHelper7 = this.analyticsHelper) === null || _this$analyticsHelper7 === void 0 ? void 0 : _this$analyticsHelper7.sendErrorEvent(error, 'Error while sending steps for a transaction');
|
|
335
272
|
throw new SendTransactionError('Error while sending steps for a transaction', error);
|
|
336
273
|
}
|
|
337
274
|
}
|
|
@@ -356,9 +293,9 @@ export class Provider extends Emitter {
|
|
|
356
293
|
this.channel.broadcast('participant:telepointer', payload, callback);
|
|
357
294
|
}
|
|
358
295
|
} catch (error) {
|
|
359
|
-
var _this$
|
|
296
|
+
var _this$analyticsHelper8;
|
|
360
297
|
// We don't want to throw errors for Presence features as they tend to self-restore
|
|
361
|
-
(_this$
|
|
298
|
+
(_this$analyticsHelper8 = this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 ? void 0 : _this$analyticsHelper8.sendErrorEvent(error, 'Error while sending message - telepointer');
|
|
362
299
|
}
|
|
363
300
|
}
|
|
364
301
|
/**
|
|
@@ -390,8 +327,8 @@ export class Provider extends Emitter {
|
|
|
390
327
|
super.unsubscribeAll();
|
|
391
328
|
this.channel.disconnect();
|
|
392
329
|
} catch (error) {
|
|
393
|
-
var _this$
|
|
394
|
-
(_this$
|
|
330
|
+
var _this$analyticsHelper9;
|
|
331
|
+
(_this$analyticsHelper9 = this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 ? void 0 : _this$analyticsHelper9.sendErrorEvent(error, 'Error while shutting down the collab provider');
|
|
395
332
|
throw new DestroyError('Error while shutting down the collab provider', error);
|
|
396
333
|
}
|
|
397
334
|
this.clearTimers();
|
|
@@ -409,8 +346,8 @@ export class Provider extends Emitter {
|
|
|
409
346
|
try {
|
|
410
347
|
this.metadataService.setTitle(title, broadcast);
|
|
411
348
|
} catch (error) {
|
|
412
|
-
var _this$
|
|
413
|
-
(_this$
|
|
349
|
+
var _this$analyticsHelper10;
|
|
350
|
+
(_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 ? void 0 : _this$analyticsHelper10.sendErrorEvent(error, 'Error while setting title');
|
|
414
351
|
throw new SetTitleError('Error while setting title', error);
|
|
415
352
|
}
|
|
416
353
|
}
|
|
@@ -426,8 +363,8 @@ export class Provider extends Emitter {
|
|
|
426
363
|
try {
|
|
427
364
|
this.metadataService.setEditorWidth(editorWidth, broadcast);
|
|
428
365
|
} catch (error) {
|
|
429
|
-
var _this$
|
|
430
|
-
(_this$
|
|
366
|
+
var _this$analyticsHelper11;
|
|
367
|
+
(_this$analyticsHelper11 = this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 ? void 0 : _this$analyticsHelper11.sendErrorEvent(error, 'Error while setting editor width');
|
|
431
368
|
throw new SetEditorWidthError('Error while setting editor width', error);
|
|
432
369
|
}
|
|
433
370
|
}
|
|
@@ -441,8 +378,8 @@ export class Provider extends Emitter {
|
|
|
441
378
|
try {
|
|
442
379
|
this.metadataService.setMetadata(metadata);
|
|
443
380
|
} catch (error) {
|
|
444
|
-
var _this$
|
|
445
|
-
(_this$
|
|
381
|
+
var _this$analyticsHelper12;
|
|
382
|
+
(_this$analyticsHelper12 = this.analyticsHelper) === null || _this$analyticsHelper12 === void 0 ? void 0 : _this$analyticsHelper12.sendErrorEvent(error, 'Error while setting metadata');
|
|
446
383
|
throw new SetMetadataError('Error while setting metadata', error);
|
|
447
384
|
}
|
|
448
385
|
}
|
package/dist/es2019/version.json
CHANGED