@atlaskit/collab-provider 8.4.0 → 8.5.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/cjs/analytics/{index.js → analytics-helper.js} +43 -4
  3. package/dist/cjs/analytics/performance.js +6 -5
  4. package/dist/cjs/channel.js +222 -224
  5. package/dist/cjs/{provider → document}/catchup.js +2 -2
  6. package/dist/cjs/document/document-service.js +617 -0
  7. package/dist/cjs/document/step-queue-state.js +51 -0
  8. package/dist/cjs/errors/error-code-mapper.js +86 -67
  9. package/dist/cjs/errors/error-types.js +251 -21
  10. package/dist/cjs/helpers/utils.js +1 -12
  11. package/dist/cjs/participants/participants-helper.js +51 -0
  12. package/dist/cjs/participants/participants-service.js +217 -0
  13. package/dist/cjs/participants/participants-state.js +53 -0
  14. package/dist/cjs/{provider/telepointers.js → participants/telepointers-helper.js} +6 -6
  15. package/dist/cjs/provider/commit-step.js +4 -4
  16. package/dist/cjs/provider/index.js +212 -774
  17. package/dist/cjs/types.js +3 -0
  18. package/dist/cjs/version-wrapper.js +1 -1
  19. package/dist/cjs/version.json +1 -1
  20. package/dist/es2019/analytics/{index.js → analytics-helper.js} +15 -4
  21. package/dist/es2019/analytics/performance.js +5 -6
  22. package/dist/es2019/channel.js +123 -116
  23. package/dist/es2019/{provider → document}/catchup.js +2 -2
  24. package/dist/es2019/document/document-service.js +495 -0
  25. package/dist/es2019/document/step-queue-state.js +30 -0
  26. package/dist/es2019/errors/error-code-mapper.js +87 -63
  27. package/dist/es2019/errors/error-types.js +143 -5
  28. package/dist/es2019/helpers/utils.js +0 -10
  29. package/dist/es2019/participants/participants-helper.js +25 -0
  30. package/dist/es2019/participants/participants-service.js +166 -0
  31. package/dist/es2019/participants/participants-state.js +28 -0
  32. package/dist/es2019/{provider/telepointers.js → participants/telepointers-helper.js} +2 -2
  33. package/dist/es2019/provider/commit-step.js +4 -4
  34. package/dist/es2019/provider/index.js +162 -637
  35. package/dist/es2019/types.js +4 -0
  36. package/dist/es2019/version-wrapper.js +1 -1
  37. package/dist/es2019/version.json +1 -1
  38. package/dist/esm/analytics/{index.js → analytics-helper.js} +43 -4
  39. package/dist/esm/analytics/performance.js +5 -6
  40. package/dist/esm/channel.js +224 -226
  41. package/dist/esm/{provider → document}/catchup.js +2 -2
  42. package/dist/esm/document/document-service.js +609 -0
  43. package/dist/esm/document/step-queue-state.js +43 -0
  44. package/dist/esm/errors/error-code-mapper.js +87 -64
  45. package/dist/esm/errors/error-types.js +243 -18
  46. package/dist/esm/helpers/utils.js +0 -10
  47. package/dist/esm/participants/participants-helper.js +43 -0
  48. package/dist/esm/participants/participants-service.js +209 -0
  49. package/dist/esm/participants/participants-state.js +45 -0
  50. package/dist/esm/{provider/telepointers.js → participants/telepointers-helper.js} +4 -4
  51. package/dist/esm/provider/commit-step.js +4 -4
  52. package/dist/esm/provider/index.js +212 -774
  53. package/dist/esm/types.js +4 -0
  54. package/dist/esm/version-wrapper.js +1 -1
  55. package/dist/esm/version.json +1 -1
  56. package/dist/types/analytics/{index.d.ts → analytics-helper.d.ts} +3 -1
  57. package/dist/types/analytics/performance.d.ts +3 -1
  58. package/dist/types/analytics/ufo.d.ts +1 -1
  59. package/dist/types/channel.d.ts +12 -5
  60. package/dist/types/document/document-service.d.ts +105 -0
  61. package/dist/types/document/step-queue-state.d.ts +16 -0
  62. package/dist/types/errors/error-code-mapper.d.ts +2 -36
  63. package/dist/types/errors/error-types.d.ts +439 -4
  64. package/dist/types/helpers/const.d.ts +2 -2
  65. package/dist/types/helpers/utils.d.ts +0 -6
  66. package/dist/types/index.d.ts +2 -1
  67. package/dist/types/participants/participants-helper.d.ts +15 -0
  68. package/dist/types/participants/participants-service.d.ts +70 -0
  69. package/dist/types/participants/participants-state.d.ts +13 -0
  70. package/dist/types/participants/telepointers-helper.d.ts +4 -0
  71. package/dist/types/provider/commit-step.d.ts +6 -6
  72. package/dist/types/provider/index.d.ts +80 -73
  73. package/dist/types/types.d.ts +47 -30
  74. package/package.json +4 -4
  75. package/report.api.md +172 -19
  76. package/dist/types/provider/telepointers.d.ts +0 -5
  77. /package/dist/types/{provider → document}/catchup.d.ts +0 -0
@@ -0,0 +1,209 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
+ import _createClass from "@babel/runtime/helpers/createClass";
4
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
6
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
7
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
8
+ import { disconnectedReasonMapper } from '../disconnected-reason-mapper';
9
+ import { EVENT_ACTION, EVENT_STATUS } from '../helpers/const';
10
+ import { telepointerFromStep } from './telepointers-helper';
11
+ import { createParticipantFromPayload as enrichParticipant, PARTICIPANT_UPDATE_INTERVAL } from './participants-helper';
12
+ import { ParticipantsState } from './participants-state';
13
+ export var ParticipantsService = /*#__PURE__*/function () {
14
+ function ParticipantsService(analyticsHelper) {
15
+ var _this = this;
16
+ var participantsState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new ParticipantsState();
17
+ _classCallCheck(this, ParticipantsService);
18
+ _defineProperty(this, "updateParticipant", /*#__PURE__*/function () {
19
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(payload, getUser, emit) {
20
+ var userId, participant, _this$analyticsHelper, isNewParticipant;
21
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
22
+ while (1) {
23
+ switch (_context.prev = _context.next) {
24
+ case 0:
25
+ userId = payload.userId; // If userId does not exist, does nothing here to prevent duplication.
26
+ if (userId) {
27
+ _context.next = 3;
28
+ break;
29
+ }
30
+ return _context.abrupt("return");
31
+ case 3:
32
+ _context.prev = 3;
33
+ _context.next = 6;
34
+ return enrichParticipant( // userId _must_ be defined, this lets the compiler know
35
+ _objectSpread(_objectSpread({}, payload), {}, {
36
+ userId: userId
37
+ }), getUser);
38
+ case 6:
39
+ participant = _context.sent;
40
+ _context.next = 12;
41
+ break;
42
+ case 9:
43
+ _context.prev = 9;
44
+ _context.t0 = _context["catch"](3);
45
+ // We don't want to throw errors for Presence features as they tend to self-restore
46
+ (_this$analyticsHelper = _this.analyticsHelper) === null || _this$analyticsHelper === void 0 ? void 0 : _this$analyticsHelper.sendErrorEvent(_context.t0, 'enriching participant');
47
+ case 12:
48
+ if (participant) {
49
+ _context.next = 14;
50
+ break;
51
+ }
52
+ return _context.abrupt("return");
53
+ case 14:
54
+ isNewParticipant = _this.participantsState.doesntHave(participant.sessionId);
55
+ _this.participantsState.setBySessionId(participant.sessionId, participant);
56
+ if (isNewParticipant) {
57
+ _context.next = 18;
58
+ break;
59
+ }
60
+ return _context.abrupt("return");
61
+ case 18:
62
+ _this.emitPresence({
63
+ joined: [participant]
64
+ }, emit, 'handling participant updated event');
65
+ case 19:
66
+ case "end":
67
+ return _context.stop();
68
+ }
69
+ }
70
+ }, _callee, null, [[3, 9]]);
71
+ }));
72
+ return function (_x, _x2, _x3) {
73
+ return _ref.apply(this, arguments);
74
+ };
75
+ }());
76
+ _defineProperty(this, "participantLeft", function (_ref2, emit) {
77
+ var sessionId = _ref2.sessionId;
78
+ _this.participantsState.removeBySessionId(sessionId);
79
+ _this.emitPresence({
80
+ left: [{
81
+ sessionId: sessionId
82
+ }]
83
+ }, emit, 'participant leaving');
84
+ });
85
+ _defineProperty(this, "disconnect", function (reason, sessionId, emit) {
86
+ var left = _this.participantsState.getParticipants();
87
+ _this.participantsState.clear();
88
+ try {
89
+ emit('disconnected', {
90
+ reason: disconnectedReasonMapper(reason),
91
+ sid: sessionId
92
+ });
93
+ } catch (error) {
94
+ var _this$analyticsHelper2;
95
+ // We don't want to throw errors for Presence features as they tend to self-restore
96
+ (_this$analyticsHelper2 = _this.analyticsHelper) === null || _this$analyticsHelper2 === void 0 ? void 0 : _this$analyticsHelper2.sendErrorEvent(error, 'emitting disconnected data');
97
+ }
98
+ if (left.length) {
99
+ _this.emitPresence({
100
+ left: left
101
+ }, emit, 'emitting presence update on disconnect');
102
+ }
103
+ });
104
+ _defineProperty(this, "updateLastActive", function () {
105
+ var userIds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
106
+ return _this.participantsState.updateLastActive(Date.now(), userIds);
107
+ });
108
+ _defineProperty(this, "participantTelepointer", function (payload, thisSessionId, getUser, emit) {
109
+ var sessionId = payload.sessionId,
110
+ selection = payload.selection,
111
+ timestamp = payload.timestamp;
112
+ var participant = _this.participantsState.getBySessionId(sessionId);
113
+ if (sessionId === thisSessionId ||
114
+ // Ignore old telepointer events
115
+ participant && participant.lastActive > timestamp) {
116
+ return;
117
+ }
118
+ var userId = payload.userId ? [payload.userId] : undefined;
119
+
120
+ // Set last active
121
+ _this.updateLastActive(userId);
122
+ _this.emitTelepointer({
123
+ type: 'telepointer',
124
+ selection: selection,
125
+ sessionId: sessionId
126
+ }, emit, 'handling participant telepointer event');
127
+ });
128
+ _defineProperty(this, "removeInactiveParticipants", function (sessionId, emit) {
129
+ clearTimeout(_this.participantUpdateTimeout);
130
+ try {
131
+ _this.filterInactive(sessionId, emit);
132
+ } catch (err) {
133
+ var _this$analyticsHelper3;
134
+ (_this$analyticsHelper3 = _this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 ? void 0 : _this$analyticsHelper3.sendErrorEvent(err, 'Failed filtering inactive participants');
135
+ }
136
+ _this.participantUpdateTimeout = window.setTimeout(function () {
137
+ return _this.removeInactiveParticipants(sessionId, emit);
138
+ }, PARTICIPANT_UPDATE_INTERVAL);
139
+ });
140
+ _defineProperty(this, "filterInactive", function (sessionId, emit) {
141
+ var now = Date.now();
142
+ var left = _this.participantsState.getParticipants().filter(function (p) {
143
+ return p.sessionId !== sessionId && now - p.lastActive > PARTICIPANT_UPDATE_INTERVAL;
144
+ });
145
+ left.forEach(function (p) {
146
+ return _this.participantsState.removeBySessionId(p.sessionId);
147
+ });
148
+ _this.emitPresence({
149
+ left: left
150
+ }, emit, 'filtering inactive participants');
151
+ });
152
+ _defineProperty(this, "emitPresence", function (data, emit, errorMessage) {
153
+ try {
154
+ var _this$analyticsHelper4;
155
+ emit('presence', data);
156
+ (_this$analyticsHelper4 = _this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 ? void 0 : _this$analyticsHelper4.sendActionEvent(EVENT_ACTION.UPDATE_PARTICIPANTS, EVENT_STATUS.SUCCESS, {
157
+ participants: _this.participantsState.size()
158
+ });
159
+ } catch (error) {
160
+ var _this$analyticsHelper5;
161
+ // We don't want to throw errors for Presence features as they tend to self-restore
162
+ (_this$analyticsHelper5 = _this.analyticsHelper) === null || _this$analyticsHelper5 === void 0 ? void 0 : _this$analyticsHelper5.sendErrorEvent(error, "Error while ".concat(errorMessage));
163
+ }
164
+ });
165
+ _defineProperty(this, "emitTelepointer", function (data, emit, errorMessage) {
166
+ try {
167
+ emit('telepointer', data);
168
+ } catch (error) {
169
+ var _this$analyticsHelper6;
170
+ // We don't want to throw errors for Presence features as they tend to self-restore
171
+ (_this$analyticsHelper6 = _this.analyticsHelper) === null || _this$analyticsHelper6 === void 0 ? void 0 : _this$analyticsHelper6.sendErrorEvent(error, "Error while ".concat(errorMessage));
172
+ }
173
+ });
174
+ this.participantsState = participantsState;
175
+ this.analyticsHelper = analyticsHelper;
176
+ }
177
+
178
+ /**
179
+ * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
180
+ * @param payload Payload from incoming socket event
181
+ * @param getUser Function to get user data from confluence
182
+ * @param emit Function to execute emit from provider socket
183
+ * @returns Awaitable Promise, due to getUser
184
+ */
185
+ _createClass(ParticipantsService, [{
186
+ key: "emitTelepointersFromSteps",
187
+ value:
188
+ /**
189
+ * Called on receiving steps, emits each step's telepointer
190
+ * @param steps Steps to extract telepointers from
191
+ * @param emit Provider emit function
192
+ */
193
+ function emitTelepointersFromSteps(steps, emit) {
194
+ var _this2 = this;
195
+ steps.forEach(function (step) {
196
+ var event = telepointerFromStep(_this2.participantsState.getParticipants(), step);
197
+ if (event) {
198
+ _this2.emitTelepointer(event, emit, 'emitting telepointers from steps');
199
+ }
200
+ });
201
+ }
202
+
203
+ /**
204
+ * Called when we receive a telepointer update from another
205
+ * participant.
206
+ */
207
+ }]);
208
+ return ParticipantsService;
209
+ }();
@@ -0,0 +1,45 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
6
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
7
+ export var ParticipantsState = /*#__PURE__*/_createClass(function ParticipantsState() {
8
+ var _this = this;
9
+ var baseParticipants = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Map();
10
+ _classCallCheck(this, ParticipantsState);
11
+ _defineProperty(this, "getBySessionId", function (sessionId) {
12
+ var participant = _this.participants.get(sessionId);
13
+ // Spread to ensure we get a deep copy
14
+ return participant ? _objectSpread({}, participant) : undefined;
15
+ });
16
+ _defineProperty(this, "setBySessionId", function (sessionId, participant) {
17
+ _this.participants.set(sessionId, participant);
18
+ });
19
+ _defineProperty(this, "getParticipants", function () {
20
+ return (
21
+ // Spread to get deep copy
22
+ _toConsumableArray(_this.participants.values()).map(function (p) {
23
+ return _objectSpread({}, p);
24
+ })
25
+ );
26
+ });
27
+ _defineProperty(this, "removeBySessionId", function (sessionId) {
28
+ return _this.participants.delete(sessionId);
29
+ });
30
+ _defineProperty(this, "clear", function () {
31
+ return _this.participants.clear();
32
+ });
33
+ _defineProperty(this, "doesntHave", function (sessionId) {
34
+ return !_this.participants.has(sessionId);
35
+ });
36
+ _defineProperty(this, "size", function () {
37
+ return _this.participants.size;
38
+ });
39
+ _defineProperty(this, "updateLastActive", function (now, userIds) {
40
+ return _this.participants.forEach(function (p) {
41
+ p.lastActive = userIds.includes(p.userId) ? now : p.lastActive;
42
+ });
43
+ });
44
+ this.participants = baseParticipants;
45
+ });
@@ -4,12 +4,12 @@ import { createLogger } from '../helpers/utils';
4
4
  import { ExperiencePerformanceTypes, ExperienceTypes, UFOExperience } from '@atlaskit/ufo';
5
5
  import { AcknowledgementResponseTypes } from '../types';
6
6
  var logger = createLogger('Telepointer', 'green');
7
- export var telepointersFromStep = function telepointersFromStep(participants, step) {
8
- var _Array$from$filter = Array.from(participants.values()).filter(function (p) {
7
+ export var telepointerFromStep = function telepointerFromStep(participants, step) {
8
+ var _participants$filter = participants.filter(function (p) {
9
9
  return p.clientId === step.clientId;
10
10
  }),
11
- _Array$from$filter2 = _slicedToArray(_Array$from$filter, 1),
12
- participant = _Array$from$filter2[0];
11
+ _participants$filter2 = _slicedToArray(_participants$filter, 1),
12
+ participant = _participants$filter2[0];
13
13
  if (participant) {
14
14
  var _node$text;
15
15
  var stepType = step.stepType,
@@ -4,8 +4,9 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
4
4
  import countBy from 'lodash/countBy';
5
5
  import { ADD_STEPS_TYPE, EVENT_ACTION, EVENT_STATUS } from '../helpers/const';
6
6
  import { AcknowledgementResponseTypes } from '../types';
7
+ import { NCS_ERROR_CODE } from '../errors/error-types';
7
8
  export var commitStep = function commitStep(_ref) {
8
- var channel = _ref.channel,
9
+ var broadcast = _ref.broadcast,
9
10
  steps = _ref.steps,
10
11
  version = _ref.version,
11
12
  userId = _ref.userId,
@@ -21,7 +22,7 @@ export var commitStep = function commitStep(_ref) {
21
22
  });
22
23
  var start = new Date().getTime();
23
24
  try {
24
- channel.broadcast('steps:commit', {
25
+ broadcast('steps:commit', {
25
26
  steps: stepsWithClientAndUserId,
26
27
  version: version,
27
28
  userId: userId
@@ -40,13 +41,12 @@ export var commitStep = function commitStep(_ref) {
40
41
  })
41
42
  });
42
43
  } else if (response.type === AcknowledgementResponseTypes.ERROR) {
43
- var _response$error, _response$error$data, _response$error2, _response$error2$data;
44
44
  onErrorHandled(response.error);
45
45
  analyticsHelper === null || analyticsHelper === void 0 ? void 0 : analyticsHelper.sendActionEvent(EVENT_ACTION.ADD_STEPS, EVENT_STATUS.FAILURE, {
46
46
  // User tried committing steps but they were rejected because:
47
47
  // - HEAD_VERSION_UPDATE_FAILED: the collab service's latest stored step tail version didn't correspond to the head version of the first step submitted
48
48
  // - VERSION_NUMBER_ALREADY_EXISTS: while storing the steps there was a conflict meaning someone else wrote steps into the database more quickly
49
- type: ((_response$error = response.error) === null || _response$error === void 0 ? void 0 : (_response$error$data = _response$error.data) === null || _response$error$data === void 0 ? void 0 : _response$error$data.code) === 'HEAD_VERSION_UPDATE_FAILED' || ((_response$error2 = response.error) === null || _response$error2 === void 0 ? void 0 : (_response$error2$data = _response$error2.data) === null || _response$error2$data === void 0 ? void 0 : _response$error2$data.code) === 'VERSION_NUMBER_ALREADY_EXISTS' ? ADD_STEPS_TYPE.REJECTED : ADD_STEPS_TYPE.ERROR,
49
+ type: response.error.data.code === NCS_ERROR_CODE.HEAD_VERSION_UPDATE_FAILED || response.error.data.code === NCS_ERROR_CODE.VERSION_NUMBER_ALREADY_EXISTS ? ADD_STEPS_TYPE.REJECTED : ADD_STEPS_TYPE.ERROR,
50
50
  latency: latency
51
51
  });
52
52
  analyticsHelper === null || analyticsHelper === void 0 ? void 0 : analyticsHelper.sendErrorEvent(response.error, 'Error while adding steps - Acknowledgement Error');