@atlaskit/collab-provider 10.4.0 → 10.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 (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-jira/tsconfig.json +6 -0
  4. package/dist/cjs/analytics/analytics-helper.js +0 -2
  5. package/dist/cjs/api/api.js +26 -14
  6. package/dist/cjs/channel.js +0 -2
  7. package/dist/cjs/document/catchupv2.js +1 -4
  8. package/dist/cjs/document/document-service.js +35 -33
  9. package/dist/cjs/helpers/utils.js +80 -1
  10. package/dist/cjs/participants/participants-service.js +3 -2
  11. package/dist/cjs/provider/commit-step.js +14 -1
  12. package/dist/cjs/provider/index.js +69 -33
  13. package/dist/cjs/version-wrapper.js +1 -1
  14. package/dist/es2019/analytics/analytics-helper.js +0 -2
  15. package/dist/es2019/api/api.js +13 -1
  16. package/dist/es2019/channel.js +0 -2
  17. package/dist/es2019/document/catchupv2.js +1 -4
  18. package/dist/es2019/document/document-service.js +8 -6
  19. package/dist/es2019/helpers/utils.js +30 -1
  20. package/dist/es2019/participants/participants-service.js +3 -2
  21. package/dist/es2019/provider/commit-step.js +15 -1
  22. package/dist/es2019/provider/index.js +40 -17
  23. package/dist/es2019/version-wrapper.js +1 -1
  24. package/dist/esm/analytics/analytics-helper.js +0 -2
  25. package/dist/esm/api/api.js +26 -14
  26. package/dist/esm/channel.js +0 -2
  27. package/dist/esm/document/catchupv2.js +1 -4
  28. package/dist/esm/document/document-service.js +35 -33
  29. package/dist/esm/helpers/utils.js +78 -1
  30. package/dist/esm/participants/participants-service.js +3 -2
  31. package/dist/esm/provider/commit-step.js +14 -1
  32. package/dist/esm/provider/index.js +71 -35
  33. package/dist/esm/version-wrapper.js +1 -1
  34. package/dist/types/document/document-service.d.ts +1 -0
  35. package/dist/types/errors/custom-errors.d.ts +1 -1
  36. package/dist/types/helpers/utils.d.ts +9 -1
  37. package/dist/types/index.d.ts +1 -1
  38. package/dist/types/participants/participants-service.d.ts +1 -0
  39. package/dist/types/provider/commit-step.d.ts +3 -1
  40. package/dist/types/types.d.ts +1 -0
  41. package/dist/types-ts4.5/document/document-service.d.ts +1 -0
  42. package/dist/types-ts4.5/errors/custom-errors.d.ts +1 -1
  43. package/dist/types-ts4.5/helpers/utils.d.ts +9 -1
  44. package/dist/types-ts4.5/index.d.ts +1 -1
  45. package/dist/types-ts4.5/participants/participants-service.d.ts +1 -0
  46. package/dist/types-ts4.5/provider/commit-step.d.ts +3 -1
  47. package/dist/types-ts4.5/types.d.ts +1 -0
  48. package/package.json +16 -6
@@ -228,8 +228,6 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
228
228
  _this.emit('steps:added', data);
229
229
  }
230
230
  });
231
- // Ignored via go/ees005
232
- // eslint-disable-next-line @typescript-eslint/max-params
233
231
  _defineProperty(_this, "fetchCatchupv2", /*#__PURE__*/function () {
234
232
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(fromVersion, clientId, catchUpOutofSync, reason) {
235
233
  var _yield$utils$requestS, steps, metadata, errorNotFound, errorCatchupv2;
@@ -89,10 +89,7 @@ var logObfuscatedSteps = function logObfuscatedSteps(steps, opt) {
89
89
  * @param clientId The ID of the currently connected session (one user can have multiple if theu have multiple tabs open)
90
90
  * @returns True if we're out of sync, false if not.
91
91
  */
92
- export var isOutOfSync = function isOutOfSync(fromVersion, currentVersion, steps, clientId
93
- // Ignored via go/ees005
94
- // eslint-disable-next-line @typescript-eslint/max-params
95
- ) {
92
+ export var isOutOfSync = function isOutOfSync(fromVersion, currentVersion, steps, clientId) {
96
93
  return (
97
94
  // If version number hasn't increased, and steps are not from our client, we're out of sync
98
95
  Boolean(fromVersion >= currentVersion && steps.some(function (step) {
@@ -21,7 +21,7 @@ import { CantSyncUpError, UpdateDocumentError } from '../errors/custom-errors';
21
21
  var CATCHUP_THROTTLE = 1 * 1000; // 1 second
22
22
 
23
23
  var noop = function noop() {};
24
- var logger = createLogger('documentService', 'black');
24
+ var logger = createLogger('documentService', 'red');
25
25
  export var DocumentService = /*#__PURE__*/function () {
26
26
  // ClientID is the unique ID for a prosemirror client. Used for step-rebasing.
27
27
 
@@ -40,8 +40,6 @@ export var DocumentService = /*#__PURE__*/function () {
40
40
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
41
41
  * @param getConnected - if the channel is currently connected
42
42
  */
43
- // Ignored via go/ees005
44
- // eslint-disable-next-line @typescript-eslint/max-params
45
43
  function DocumentService(participantsService, analyticsHelper, fetchCatchupv2, fetchReconcile,
46
44
  // Ignored via go/ees005
47
45
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -57,6 +55,7 @@ export var DocumentService = /*#__PURE__*/function () {
57
55
  _defineProperty(this, "stepRejectCounter", 0);
58
56
  _defineProperty(this, "aggressiveCatchup", false);
59
57
  _defineProperty(this, "catchUpOutofSync", false);
58
+ _defineProperty(this, "hasRecovered", false);
60
59
  /**
61
60
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
62
61
  * @param reason - optional reason to attach.
@@ -308,21 +307,24 @@ export var DocumentService = /*#__PURE__*/function () {
308
307
  while (1) switch (_context3.prev = _context3.next) {
309
308
  case 0:
310
309
  doc = _ref6.doc, version = _ref6.version, metadata = _ref6.metadata, targetClientId = _ref6.targetClientId;
310
+ if (!targetClientId) {
311
+ _this.hasRecovered = true;
312
+ }
311
313
  if (!(targetClientId && _this.clientId !== targetClientId)) {
312
- _context3.next = 3;
314
+ _context3.next = 4;
313
315
  break;
314
316
  }
315
317
  return _context3.abrupt("return");
316
- case 3:
318
+ case 4:
317
319
  // We preserve these as they will be lost apon this.updateDocument. This is because we are using document recovery.
318
320
  // We can then reconcile the document with the preserved state.
319
321
  unconfirmedSteps = _this.getUnconfirmedSteps();
320
- _context3.next = 6;
322
+ _context3.next = 7;
321
323
  return _this.getCurrentState();
322
- case 6:
324
+ case 7:
323
325
  currentState = _context3.sent;
324
326
  useReconcile = Boolean((unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length) && currentState && !targetClientId);
325
- _context3.prev = 8;
327
+ _context3.prev = 9;
326
328
  // Reset the editor,
327
329
  // - Replace the document, keep in sync with the server
328
330
  // - Replace the version number, so editor is in sync with NCS server and can commit new changes.
@@ -337,10 +339,10 @@ export var DocumentService = /*#__PURE__*/function () {
337
339
  });
338
340
  _this.metadataService.updateMetadata(metadata);
339
341
  if (!fg('restore_localstep_fallback_reconcile')) {
340
- _context3.next = 25;
342
+ _context3.next = 26;
341
343
  break;
342
344
  }
343
- _context3.prev = 12;
345
+ _context3.prev = 13;
344
346
  (_this$analyticsHelper13 = _this.analyticsHelper) === null || _this$analyticsHelper13 === void 0 || _this$analyticsHelper13.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.INFO, {
345
347
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
346
348
  hasTitle: !!(metadata !== null && metadata !== void 0 && metadata.title),
@@ -351,35 +353,35 @@ export var DocumentService = /*#__PURE__*/function () {
351
353
  if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
352
354
  _this.applyLocalSteps(unconfirmedSteps);
353
355
  }
354
- _context3.next = 23;
356
+ _context3.next = 24;
355
357
  break;
356
- case 17:
357
- _context3.prev = 17;
358
- _context3.t0 = _context3["catch"](12);
358
+ case 18:
359
+ _context3.prev = 18;
360
+ _context3.t0 = _context3["catch"](13);
359
361
  (_this$analyticsHelper14 = _this.analyticsHelper) === null || _this$analyticsHelper14 === void 0 || _this$analyticsHelper14.sendErrorEvent(_context3.t0, "Error while onRestore with applyLocalSteps. Will fallback to fetchReconcile");
360
362
  useReconcile = true;
361
- _context3.next = 23;
363
+ _context3.next = 24;
362
364
  return _this.fetchReconcile(JSON.stringify(currentState.content), 'fe-restore');
363
- case 23:
364
- _context3.next = 31;
365
+ case 24:
366
+ _context3.next = 32;
365
367
  break;
366
- case 25:
368
+ case 26:
367
369
  if (!(useReconcile && currentState)) {
368
- _context3.next = 30;
370
+ _context3.next = 31;
369
371
  break;
370
372
  }
371
- _context3.next = 28;
373
+ _context3.next = 29;
372
374
  return _this.fetchReconcile(JSON.stringify(currentState.content), 'fe-restore');
373
- case 28:
374
- _context3.next = 31;
375
+ case 29:
376
+ _context3.next = 32;
375
377
  break;
376
- case 30:
378
+ case 31:
377
379
  if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
378
380
  // we don't want to use reconcile for restore triggered by catchup client out of sync (when targetClientId is provided)
379
381
  // as this results in all changes made while the client was out of sync being lost
380
382
  _this.applyLocalSteps(unconfirmedSteps);
381
383
  }
382
- case 31:
384
+ case 32:
383
385
  (_this$analyticsHelper15 = _this.analyticsHelper) === null || _this$analyticsHelper15 === void 0 || _this$analyticsHelper15.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.SUCCESS, {
384
386
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
385
387
  hasTitle: !!(metadata !== null && metadata !== void 0 && metadata.title),
@@ -388,11 +390,11 @@ export var DocumentService = /*#__PURE__*/function () {
388
390
  targetClientId: targetClientId,
389
391
  triggeredByCatchup: targetClientId ? true : false
390
392
  });
391
- _context3.next = 39;
393
+ _context3.next = 40;
392
394
  break;
393
- case 34:
394
- _context3.prev = 34;
395
- _context3.t1 = _context3["catch"](8);
395
+ case 35:
396
+ _context3.prev = 35;
397
+ _context3.t1 = _context3["catch"](9);
396
398
  (_this$analyticsHelper16 = _this.analyticsHelper) === null || _this$analyticsHelper16 === void 0 || _this$analyticsHelper16.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.FAILURE, {
397
399
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
398
400
  useReconcile: useReconcile,
@@ -409,11 +411,11 @@ export var DocumentService = /*#__PURE__*/function () {
409
411
  code: INTERNAL_ERROR_CODE.DOCUMENT_RESTORE_ERROR
410
412
  }
411
413
  });
412
- case 39:
414
+ case 40:
413
415
  case "end":
414
416
  return _context3.stop();
415
417
  }
416
- }, _callee3, null, [[8, 34], [12, 17]]);
418
+ }, _callee3, null, [[9, 35], [13, 18]]);
417
419
  }));
418
420
  return function (_x3) {
419
421
  return _ref7.apply(this, arguments);
@@ -824,8 +826,6 @@ export var DocumentService = /*#__PURE__*/function () {
824
826
  * Send steps from transaction to other participants
825
827
  * It needs the superfluous arguments because we keep the interface of the send API the same as the Synchrony plugin
826
828
  */
827
- // Ignored via go/ees005
828
- // eslint-disable-next-line @typescript-eslint/max-params
829
829
  function send(_tr, _oldState, newState, sendAnalyticsEvent) {
830
830
  var unconfirmedStepsData = sendableSteps(newState);
831
831
  var version = this.getVersionFromCollabState(newState, 'collab-provider: send');
@@ -883,7 +883,9 @@ export var DocumentService = /*#__PURE__*/function () {
883
883
  onErrorHandled: this.onErrorHandled,
884
884
  analyticsHelper: this.analyticsHelper,
885
885
  emit: this.providerEmitCallback,
886
- __livePage: this.options.__livePage
886
+ __livePage: this.options.__livePage,
887
+ hasRecovered: this.hasRecovered,
888
+ collabMode: this.participantsService.getCollabMode()
887
889
  });
888
890
  }
889
891
  }]);
@@ -1,7 +1,11 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
1
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
2
4
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
5
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
6
  import { scrubAdf } from '@atlaskit/adf-utils/scrub';
7
+ import { sendableSteps } from '@atlaskit/prosemirror-collab';
8
+ import { CustomError } from '../errors/custom-errors';
5
9
  export var createLogger = function createLogger(prefix) {
6
10
  var color = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'blue';
7
11
  return (
@@ -191,4 +195,77 @@ var stepToAdf = function stepToAdf(step) {
191
195
  });
192
196
  }
193
197
  return [];
194
- };
198
+ };
199
+ export function logObfuscatedSteps(_x, _x2) {
200
+ return _logObfuscatedSteps.apply(this, arguments);
201
+ }
202
+ function _logObfuscatedSteps() {
203
+ _logObfuscatedSteps = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(oldState, newState) {
204
+ var _states$new, _states$old, stepsFromOldState, stepsFromNewState, states;
205
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
206
+ while (1) switch (_context.prev = _context.next) {
207
+ case 0:
208
+ _context.prev = 0;
209
+ stepsFromOldState = '', stepsFromNewState = '';
210
+ states = {
211
+ old: oldState ? sendableSteps(oldState) : null,
212
+ new: sendableSteps(newState)
213
+ };
214
+ if (!((_states$new = states.new) !== null && _states$new !== void 0 && _states$new.steps)) {
215
+ _context.next = 7;
216
+ break;
217
+ }
218
+ _context.next = 6;
219
+ return toObfuscatedSteps(states.new.steps);
220
+ case 6:
221
+ stepsFromNewState = _context.sent;
222
+ case 7:
223
+ if (!((_states$old = states.old) !== null && _states$old !== void 0 && _states$old.steps)) {
224
+ _context.next = 11;
225
+ break;
226
+ }
227
+ _context.next = 10;
228
+ return toObfuscatedSteps(states.old.steps);
229
+ case 10:
230
+ stepsFromOldState = _context.sent;
231
+ case 11:
232
+ return _context.abrupt("return", {
233
+ stepsFromOldState: stepsFromOldState,
234
+ stepsFromNewState: stepsFromNewState
235
+ });
236
+ case 14:
237
+ _context.prev = 14;
238
+ _context.t0 = _context["catch"](0);
239
+ return _context.abrupt("return", new CustomError('Failed to obfuscate steps', _context.t0));
240
+ case 17:
241
+ case "end":
242
+ return _context.stop();
243
+ }
244
+ }, _callee, null, [[0, 14]]);
245
+ }));
246
+ return _logObfuscatedSteps.apply(this, arguments);
247
+ }
248
+ export function toObfuscatedSteps(_x3) {
249
+ return _toObfuscatedSteps.apply(this, arguments);
250
+ }
251
+ function _toObfuscatedSteps() {
252
+ _toObfuscatedSteps = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(steps) {
253
+ var _steps;
254
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
255
+ while (1) switch (_context2.prev = _context2.next) {
256
+ case 0:
257
+ _context2.next = 2;
258
+ return Promise.resolve(steps.slice().map(function (s) {
259
+ return s.toJSON();
260
+ }));
261
+ case 2:
262
+ _steps = _context2.sent;
263
+ return _context2.abrupt("return", JSON.stringify(getObfuscatedSteps(_steps)));
264
+ case 4:
265
+ case "end":
266
+ return _context2.stop();
267
+ }
268
+ }, _callee2);
269
+ }));
270
+ return _toObfuscatedSteps.apply(this, arguments);
271
+ }
@@ -24,8 +24,6 @@ var SEND_PRESENCE_INTERVAL = 150 * 1000; // 150 seconds
24
24
  * @param sendPresenceJoined Callback to Channel class
25
25
  */
26
26
  export var ParticipantsService = /*#__PURE__*/function () {
27
- // Ignored via go/ees005
28
- // eslint-disable-next-line @typescript-eslint/max-params
29
27
  function ParticipantsService(analyticsHelper) {
30
28
  var _this = this;
31
29
  var participantsState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new ParticipantsState();
@@ -390,6 +388,9 @@ export var ParticipantsService = /*#__PURE__*/function () {
390
388
  _defineProperty(this, "getAIProviderParticipants", function () {
391
389
  return _this.participantsState.getAIProviderParticipants();
392
390
  });
391
+ _defineProperty(this, "getCollabMode", function () {
392
+ return _this.participantsState.size() > 1 ? 'collab' : 'single';
393
+ });
393
394
  this.analyticsHelper = analyticsHelper;
394
395
  this.participantsState = participantsState;
395
396
  this.emit = emit;
@@ -20,7 +20,9 @@ export var commitStepQueue = function commitStepQueue(_ref) {
20
20
  onErrorHandled = _ref.onErrorHandled,
21
21
  analyticsHelper = _ref.analyticsHelper,
22
22
  emit = _ref.emit,
23
- __livePage = _ref.__livePage;
23
+ __livePage = _ref.__livePage,
24
+ hasRecovered = _ref.hasRecovered,
25
+ collabMode = _ref.collabMode;
24
26
  if (!readyToCommit) {
25
27
  logger('Not ready to commit, skip');
26
28
  return;
@@ -62,6 +64,16 @@ export var commitStepQueue = function commitStepQueue(_ref) {
62
64
  return step;
63
65
  });
64
66
  }
67
+
68
+ // tag unconfirmed steps sent after page has been recovered during client's editing session
69
+ if (hasRecovered && fg('tag_unconfirmed_steps_after_recovery')) {
70
+ stepsWithClientAndUserId = stepsWithClientAndUserId.map(function (step) {
71
+ step.metadata = _objectSpread(_objectSpread({}, step.metadata), {}, {
72
+ unconfirmedStepAfterRecovery: true
73
+ });
74
+ return step;
75
+ });
76
+ }
65
77
  var start = new Date().getTime();
66
78
  emit('commit-status', {
67
79
  status: 'attempt',
@@ -69,6 +81,7 @@ export var commitStepQueue = function commitStepQueue(_ref) {
69
81
  });
70
82
  try {
71
83
  broadcast('steps:commit', {
84
+ collabMode: collabMode,
72
85
  steps: stepsWithClientAndUserId,
73
86
  version: version,
74
87
  userId: userId
@@ -13,12 +13,13 @@ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstruct
13
13
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
14
14
  function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
15
15
  import { v4 as uuidv4 } from 'uuid';
16
+ import { fg } from '@atlaskit/platform-feature-flags';
16
17
  import { Emitter } from '../emitter';
17
18
  import { Channel } from '../channel';
18
- import { createLogger } from '../helpers/utils';
19
+ import { createLogger, logObfuscatedSteps } from '../helpers/utils';
19
20
  import AnalyticsHelper from '../analytics/analytics-helper';
20
21
  import { telepointerCallback } from '../participants/telepointers-helper';
21
- import { DestroyError, GetCurrentStateError, GetFinalAcknowledgedStateError, ProviderInitialisationError, SendTransactionError, SetEditorWidthError, SetMetadataError, SetTitleError } from '../errors/custom-errors';
22
+ import { CustomError, DestroyError, GetCurrentStateError, GetFinalAcknowledgedStateError, ProviderInitialisationError, SendTransactionError, SetEditorWidthError, SetMetadataError, SetTitleError } from '../errors/custom-errors';
22
23
  import { NCS_ERROR_CODE } from '../errors/ncs-errors';
23
24
  import { MetadataService } from '../metadata/metadata-service';
24
25
  import { DocumentService } from '../document/document-service';
@@ -155,7 +156,29 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
155
156
  _this.emit('permission', permit);
156
157
  }).on('steps:added', _this.documentService.onStepsAdded).on('metadata:changed', _this.metadataService.onMetadataChanged).on('participant:telepointer', function (payload) {
157
158
  return _this.participantsService.onParticipantTelepointer(payload, _this.sessionId);
158
- }).on('participant:activity-join', _this.participantsService.onParticipantActivityJoin).on('participant:activity-ack', _this.participantsService.onParticipantActivityAck).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(shouldSkipDocumentInit);
159
+ }).on('participant:activity-join', _this.participantsService.onParticipantActivityJoin).on('participant:activity-ack', _this.participantsService.onParticipantActivityAck).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', /*#__PURE__*/function () {
160
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(status) {
161
+ var isLocked;
162
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
163
+ while (1) switch (_context.prev = _context.next) {
164
+ case 0:
165
+ _context.next = 2;
166
+ return _this.namespaceService.onNamespaceStatusChanged(status);
167
+ case 2:
168
+ isLocked = _this.namespaceService.getIsNamespaceLocked();
169
+ _this.emit('namespace-lock:check', {
170
+ isLocked: isLocked
171
+ });
172
+ case 4:
173
+ case "end":
174
+ return _context.stop();
175
+ }
176
+ }, _callee);
177
+ }));
178
+ return function (_x) {
179
+ return _ref4.apply(this, arguments);
180
+ };
181
+ }()).connect(shouldSkipDocumentInit);
159
182
  });
160
183
  _defineProperty(_this, "setUserId", function (id) {
161
184
  _this.userId = id;
@@ -202,8 +225,8 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
202
225
  return _this.aiProviderActiveIds;
203
226
  });
204
227
  // Note: this gets triggered on page reload for Firefox (not other browsers) because of closeOnBeforeunload: false
205
- _defineProperty(_this, "onDisconnected", function (_ref4) {
206
- var reason = _ref4.reason;
228
+ _defineProperty(_this, "onDisconnected", function (_ref5) {
229
+ var reason = _ref5.reason;
207
230
  _this.disconnectedAt = Date.now();
208
231
  _this.participantsService.disconnect(reason, _this.sessionId);
209
232
  });
@@ -218,52 +241,52 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
218
241
  * Used for draft sync, a process running every 5s for the first editor of a document to sync the document to the Confluence back-end.
219
242
  * @throws {GetCurrentStateError} Something went wrong while returning the current state
220
243
  */
221
- _defineProperty(_this, "getCurrentState", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
244
+ _defineProperty(_this, "getCurrentState", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
222
245
  var _this$analyticsHelper4;
223
- return _regeneratorRuntime.wrap(function _callee$(_context) {
224
- while (1) switch (_context.prev = _context.next) {
246
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
247
+ while (1) switch (_context2.prev = _context2.next) {
225
248
  case 0:
226
- _context.prev = 0;
227
- _context.next = 3;
249
+ _context2.prev = 0;
250
+ _context2.next = 3;
228
251
  return _this.documentService.getCurrentState();
229
252
  case 3:
230
- return _context.abrupt("return", _context.sent);
253
+ return _context2.abrupt("return", _context2.sent);
231
254
  case 6:
232
- _context.prev = 6;
233
- _context.t0 = _context["catch"](0);
234
- (_this$analyticsHelper4 = _this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 || _this$analyticsHelper4.sendErrorEvent(_context.t0, 'Error while returning ADF version of current draft document');
235
- throw new GetCurrentStateError('Error while returning the current state of the draft document', _context.t0);
255
+ _context2.prev = 6;
256
+ _context2.t0 = _context2["catch"](0);
257
+ (_this$analyticsHelper4 = _this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 || _this$analyticsHelper4.sendErrorEvent(_context2.t0, 'Error while returning ADF version of current draft document');
258
+ throw new GetCurrentStateError('Error while returning the current state of the draft document', _context2.t0);
236
259
  case 10:
237
260
  case "end":
238
- return _context.stop();
261
+ return _context2.stop();
239
262
  }
240
- }, _callee, null, [[0, 6]]);
263
+ }, _callee2, null, [[0, 6]]);
241
264
  })));
242
265
  /**
243
266
  * Return the final acknowledged (by NCS) ADF version of the current draft document, together with it's title and the current step version.
244
267
  * Used when returning the document to Confluence on publish.
245
268
  * @throws {GetFinalAcknowledgedStateError} Something went wrong while returning the acknowledged state
246
269
  */
247
- _defineProperty(_this, "getFinalAcknowledgedState", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
270
+ _defineProperty(_this, "getFinalAcknowledgedState", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
248
271
  var _this$analyticsHelper5;
249
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
250
- while (1) switch (_context2.prev = _context2.next) {
272
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
273
+ while (1) switch (_context3.prev = _context3.next) {
251
274
  case 0:
252
- _context2.prev = 0;
253
- _context2.next = 3;
275
+ _context3.prev = 0;
276
+ _context3.next = 3;
254
277
  return _this.documentService.getFinalAcknowledgedState();
255
278
  case 3:
256
- return _context2.abrupt("return", _context2.sent);
279
+ return _context3.abrupt("return", _context3.sent);
257
280
  case 6:
258
- _context2.prev = 6;
259
- _context2.t0 = _context2["catch"](0);
260
- (_this$analyticsHelper5 = _this.analyticsHelper) === null || _this$analyticsHelper5 === void 0 || _this$analyticsHelper5.sendErrorEvent(_context2.t0, 'Error while returning ADF version of the final draft document');
261
- throw new GetFinalAcknowledgedStateError('Error while returning the final acknowledged state of the draft document', _context2.t0);
281
+ _context3.prev = 6;
282
+ _context3.t0 = _context3["catch"](0);
283
+ (_this$analyticsHelper5 = _this.analyticsHelper) === null || _this$analyticsHelper5 === void 0 || _this$analyticsHelper5.sendErrorEvent(_context3.t0, 'Error while returning ADF version of the final draft document');
284
+ throw new GetFinalAcknowledgedStateError('Error while returning the final acknowledged state of the draft document', _context3.t0);
262
285
  case 10:
263
286
  case "end":
264
- return _context2.stop();
287
+ return _context3.stop();
265
288
  }
266
- }, _callee2, null, [[0, 6]]);
289
+ }, _callee3, null, [[0, 6]]);
267
290
  })));
268
291
  _defineProperty(_this, "getUnconfirmedSteps", function () {
269
292
  return _this.documentService.getUnconfirmedSteps();
@@ -352,10 +375,10 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
352
375
  */
353
376
  }, {
354
377
  key: "setup",
355
- value: function setup(_ref7) {
356
- var getState = _ref7.getState,
357
- editorApi = _ref7.editorApi,
358
- onSyncUpError = _ref7.onSyncUpError;
378
+ value: function setup(_ref8) {
379
+ var getState = _ref8.getState,
380
+ editorApi = _ref8.editorApi,
381
+ onSyncUpError = _ref8.onSyncUpError;
359
382
  this.checkForCookies();
360
383
  try {
361
384
  // Ignored via go/ees005
@@ -449,16 +472,29 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
449
472
  }, {
450
473
  key: "send",
451
474
  value: function send(_tr, _oldState, newState) {
475
+ var _this2 = this;
452
476
  try {
453
477
  if (this.isViewOnly()) {
454
- var _this$analyticsHelper10;
455
478
  var error = {
456
479
  message: 'Attempted to send steps in view only mode',
457
480
  data: {
458
481
  code: INTERNAL_ERROR_CODE.VIEW_ONLY_STEPS_ERROR
459
482
  }
460
483
  };
461
- (_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 || _this$analyticsHelper10.sendErrorEvent(error, error.message);
484
+ if (fg('log_obfuscated_steps_for_view_only')) {
485
+ logObfuscatedSteps(_oldState, newState).then(function (attributes) {
486
+ var _this2$analyticsHelpe;
487
+ var stepAttributes = attributes instanceof CustomError ? {} : _objectSpread({}, attributes);
488
+ var stepsError = new CustomError(error.message, error, _objectSpread({}, stepAttributes));
489
+ (_this2$analyticsHelpe = _this2.analyticsHelper) === null || _this2$analyticsHelpe === void 0 || _this2$analyticsHelpe.sendErrorEvent(stepsError, stepsError.message);
490
+ }).catch(function (err) {
491
+ var _this2$analyticsHelpe2;
492
+ return (_this2$analyticsHelpe2 = _this2.analyticsHelper) === null || _this2$analyticsHelpe2 === void 0 ? void 0 : _this2$analyticsHelpe2.sendErrorEvent(err, err.message);
493
+ });
494
+ } else {
495
+ var _this$analyticsHelper10;
496
+ (_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 || _this$analyticsHelper10.sendErrorEvent(error, error.message);
497
+ }
462
498
  return;
463
499
  }
464
500
  // Don't send steps while the document is locked (eg. when restoring the document)
@@ -1,5 +1,5 @@
1
1
  export var name = "@atlaskit/collab-provider";
2
- export var version = "10.4.0";
2
+ export var version = "10.5.0";
3
3
  export var nextMajorVersion = function nextMajorVersion() {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -27,6 +27,7 @@ export declare class DocumentService implements DocumentServiceInterface {
27
27
  private stepRejectCounter;
28
28
  private aggressiveCatchup;
29
29
  private catchUpOutofSync;
30
+ private hasRecovered;
30
31
  private clientId?;
31
32
  onErrorHandled: (error: InternalError) => void;
32
33
  /**
@@ -1,5 +1,5 @@
1
1
  import type { CantSyncUpErrorAttributes, DocumentUpdateErrorAttributes } from '../helpers/const';
2
- type ValidEventAttributeType = boolean | string | number;
2
+ type ValidEventAttributeType = boolean | string | number | object;
3
3
  export declare class CustomError extends Error {
4
4
  extraEventAttributes?: {
5
5
  [key: string]: ValidEventAttributeType;
@@ -1,8 +1,10 @@
1
1
  import { type ADFEntity } from '@atlaskit/adf-utils/types';
2
2
  import type { ProductInformation } from '../types';
3
3
  import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
4
+ import type { EditorState } from '@atlaskit/editor-prosemirror/state';
4
5
  import type { StepJson } from '@atlaskit/editor-common/collab';
5
- import type { Node as ProseMirrorNode } from '@atlaskit/editor-prosemirror/model';
6
+ import { Node as ProseMirrorNode } from '@atlaskit/editor-prosemirror/model';
7
+ import { CustomError } from '../errors/custom-errors';
6
8
  export declare const createLogger: (prefix: string, color?: string) => (msg: string, data?: any) => void;
7
9
  export declare function sleep(ms: number): Promise<unknown>;
8
10
  export declare const isAIProviderID: (id: string) => boolean;
@@ -50,5 +52,11 @@ export declare const getObfuscatedSteps: (steps: StepJson[], endIndex?: number |
50
52
  traceId?: string | undefined;
51
53
  reqId?: string | undefined;
52
54
  schemaVersion?: string | undefined;
55
+ unconfirmedStepAfterRecovery?: boolean | undefined;
53
56
  } | undefined;
54
57
  }[];
58
+ export declare function logObfuscatedSteps(oldState: EditorState | null, newState: EditorState): Promise<CustomError | {
59
+ stepsFromOldState: string;
60
+ stepsFromNewState: string;
61
+ }>;
62
+ export declare function toObfuscatedSteps(steps: readonly ProseMirrorStep[]): Promise<string>;
@@ -1,4 +1,4 @@
1
1
  export { Provider } from './provider';
2
2
  export type { CollabEventDisconnectedData, Socket } from './types';
3
- export type { NewCollabSyncUpErrorAttributes, ResolvedEditorState, CollabMetadataPayload, CollabEventInitData, CollabInitPayload, CollabEventConnectionData, CollabConnectedPayload, CollabDisconnectedPayload, CollabDataPayload, CollabActivityData, CollabTelepointerPayload, CollabPresencePayload, CollabLocalStepsPayload, CollabPermissionEventPayload, CollabEventRemoteData, CollabEventPresenceData, CollabActivityJoinPayload, CollabActivityAckPayload, CollabEventConnectingData, CollabEventTelepointerData, CollabSendableSelection, CollabParticipant, CollabEvents, SyncUpErrorFunction, CollabEditProvider, ProviderError, ProviderParticipant, CollabEventLocalStepData, UserPermitType, } from '@atlaskit/editor-common/collab';
3
+ export type { NewCollabSyncUpErrorAttributes, ResolvedEditorState, CollabMetadataPayload, CollabEventInitData, CollabInitPayload, CollabEventConnectionData, CollabConnectedPayload, CollabDisconnectedPayload, CollabDataPayload, CollabActivityData, CollabTelepointerPayload, CollabPresencePayload, CollabLocalStepsPayload, CollabPermissionEventPayload, CollabEventRemoteData, CollabEventPresenceData, CollabActivityJoinPayload, CollabActivityAckPayload, CollabEventConnectingData, CollabEventTelepointerData, CollabSendableSelection, CollabParticipant, CollabEvents, SyncUpErrorFunction, CollabEditProvider, ProviderError, ProviderParticipant, CollabEventLocalStepData, UserPermitType, CollabNamespaceLockCheckPayload, } from '@atlaskit/editor-common/collab';
4
4
  export { PROVIDER_ERROR_CODE } from '@atlaskit/editor-common/collab';
@@ -119,4 +119,5 @@ export declare class ParticipantsService {
119
119
  */
120
120
  getParticipants: () => ProviderParticipant[];
121
121
  getAIProviderParticipants: () => ProviderParticipant[];
122
+ getCollabMode: () => "collab" | "single";
122
123
  }
@@ -5,7 +5,7 @@ import type AnalyticsHelper from '../analytics/analytics-helper';
5
5
  import type { InternalError } from '../errors/internal-errors';
6
6
  export declare let readyToCommit: boolean;
7
7
  export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
8
- export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, }: {
8
+ export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, }: {
9
9
  broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void;
10
10
  steps: readonly ProseMirrorStep[];
11
11
  version: number;
@@ -16,4 +16,6 @@ export declare const commitStepQueue: ({ broadcast, steps, version, userId, clie
16
16
  analyticsHelper?: AnalyticsHelper | undefined;
17
17
  emit: (evt: keyof CollabEvents, data: CollabCommitStatusEventPayload) => void;
18
18
  __livePage: boolean;
19
+ hasRecovered: boolean;
20
+ collabMode: string;
19
21
  }) => void;
@@ -188,6 +188,7 @@ export type ChannelEvent = {
188
188
  'participant:updated': PresencePayload;
189
189
  'steps:commit': StepsPayload & {
190
190
  userId: string;
191
+ collabMode: string;
191
192
  };
192
193
  'steps:added': StepsPayload;
193
194
  'metadata:changed': Metadata;
@@ -27,6 +27,7 @@ export declare class DocumentService implements DocumentServiceInterface {
27
27
  private stepRejectCounter;
28
28
  private aggressiveCatchup;
29
29
  private catchUpOutofSync;
30
+ private hasRecovered;
30
31
  private clientId?;
31
32
  onErrorHandled: (error: InternalError) => void;
32
33
  /**
@@ -1,5 +1,5 @@
1
1
  import type { CantSyncUpErrorAttributes, DocumentUpdateErrorAttributes } from '../helpers/const';
2
- type ValidEventAttributeType = boolean | string | number;
2
+ type ValidEventAttributeType = boolean | string | number | object;
3
3
  export declare class CustomError extends Error {
4
4
  extraEventAttributes?: {
5
5
  [key: string]: ValidEventAttributeType;