@atlaskit/editor-synced-block-provider 8.4.4 → 8.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/cjs/common/types.js +14 -0
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +115 -35
- package/dist/cjs/utils/errorHandling.js +28 -5
- package/dist/es2019/common/types.js +16 -0
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +96 -31
- package/dist/es2019/utils/errorHandling.js +31 -3
- package/dist/esm/common/types.js +16 -0
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +116 -36
- package/dist/esm/utils/errorHandling.js +28 -5
- package/dist/types/common/types.d.ts +15 -0
- package/dist/types/entry-points/common-types.d.ts +1 -1
- package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +20 -2
- package/dist/types/utils/errorHandling.d.ts +18 -2
- package/package.json +3 -3
|
@@ -12,12 +12,20 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
12
12
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
13
13
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
14
14
|
import { SyncBlockError } from '../common/types';
|
|
15
|
-
import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload, getSourceInfoErrorPayload, updateSuccessPayload, createSuccessPayload, deleteSuccessPayload, fetchReferencesErrorPayload, buildErrorAttribution } from '../utils/errorHandling';
|
|
15
|
+
import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload, getSourceInfoErrorPayload, updateSuccessPayload, createSuccessPayload, createSuccessPayloadNew, deleteSuccessPayload, fetchReferencesErrorPayload, buildErrorAttribution } from '../utils/errorHandling';
|
|
16
16
|
import { getCreateSourceExperience, getDeleteSourceExperience, getSaveSourceExperience, getFetchSourceInfoExperience } from '../utils/experienceTracking';
|
|
17
17
|
import { convertSyncBlockPMNodeToSyncBlockData, getSourceProductFromResourceIdSafe } from '../utils/utils';
|
|
18
18
|
/** Maximum time (ms) flush() will wait for in-flight block creations before proceeding. */
|
|
19
19
|
var FLUSH_CREATION_AWAIT_TIMEOUT_MS = 1000;
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Window (ms) within which a repeated `syncedBlockDelete` emission for the same
|
|
23
|
+
* resourceId is suppressed. The same logical removal can re-fire across
|
|
24
|
+
* rebased/remote/redo transactions; a short window collapses those bursts to one
|
|
25
|
+
* event while still allowing a genuine delete→recreate→delete later.
|
|
26
|
+
*/
|
|
27
|
+
var DELETE_DEDUPE_WINDOW_MS = 5000;
|
|
28
|
+
|
|
21
29
|
// A store manager responsible for the lifecycle and state management of source sync blocks in an editor instance.
|
|
22
30
|
// Designed to manage local in-memory state and synchronize with an external data provider.
|
|
23
31
|
// Supports create, flush, and delete operations for source sync blocks.
|
|
@@ -44,6 +52,12 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
44
52
|
* multiple blocks are created concurrently. See EDITOR-7112.
|
|
45
53
|
*/
|
|
46
54
|
_defineProperty(this, "creationsTimedOutDuringFlush", new Set());
|
|
55
|
+
/**
|
|
56
|
+
* resourceId -> timestamp (ms) of the last `syncedBlockDelete` emission, used
|
|
57
|
+
* to suppress duplicates within {@link DELETE_DEDUPE_WINDOW_MS}. Only consulted
|
|
58
|
+
* behind `platform_editor_blocks_patch_4`.
|
|
59
|
+
*/
|
|
60
|
+
_defineProperty(this, "recentDeleteEmissions", new Map());
|
|
47
61
|
_defineProperty(this, "setPendingDeletion", function (Ids, value) {
|
|
48
62
|
if (_this.viewMode === 'view') {
|
|
49
63
|
return;
|
|
@@ -388,12 +402,18 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
388
402
|
}
|
|
389
403
|
if (success) {
|
|
390
404
|
var _this$fireAnalyticsEv4;
|
|
391
|
-
|
|
405
|
+
var sourceProduct = getSourceProductFromResourceIdSafe(resourceId);
|
|
406
|
+
(_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 || _this$fireAnalyticsEv4.call(this, createSuccessPayload(resourceId || '', sourceProduct));
|
|
407
|
+
// Operational create-success event with the join key.
|
|
408
|
+
if (fg('platform_editor_blocks_patch_4')) {
|
|
409
|
+
var _this$fireAnalyticsEv5, _this$syncBlockCache$;
|
|
410
|
+
(_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 || _this$fireAnalyticsEv5.call(this, createSuccessPayloadNew(resourceId || '', (_this$syncBlockCache$ = this.syncBlockCache.get(resourceId)) === null || _this$syncBlockCache$ === void 0 ? void 0 : _this$syncBlockCache$.blockInstanceId, sourceProduct));
|
|
411
|
+
}
|
|
392
412
|
} else {
|
|
393
|
-
var _this$
|
|
413
|
+
var _this$fireAnalyticsEv6;
|
|
394
414
|
// Delete the node from cache if fail to create so it's not flushed to BE
|
|
395
415
|
this.syncBlockCache.delete(resourceId || '');
|
|
396
|
-
(_this$
|
|
416
|
+
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 || _this$fireAnalyticsEv6.call(this, createErrorPayload('Fail to create bodied sync block', resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
397
417
|
}
|
|
398
418
|
}
|
|
399
419
|
}, {
|
|
@@ -493,20 +513,76 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
493
513
|
});
|
|
494
514
|
this.pendingCreationPromises.set(resourceId, creationPromise);
|
|
495
515
|
} catch (error) {
|
|
496
|
-
var _this$
|
|
516
|
+
var _this$fireAnalyticsEv7;
|
|
497
517
|
if (this.isPendingCreation(resourceId)) {
|
|
498
518
|
this.commitPendingCreation(false, resourceId);
|
|
499
519
|
}
|
|
500
520
|
logException(error, {
|
|
501
521
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
502
522
|
});
|
|
503
|
-
(_this$
|
|
523
|
+
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 || _this$fireAnalyticsEv7.call(this, createErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
504
524
|
}
|
|
505
525
|
}
|
|
526
|
+
}, {
|
|
527
|
+
key: "pruneRecentDeleteEmissions",
|
|
528
|
+
value:
|
|
529
|
+
/**
|
|
530
|
+
* Drop dedupe entries older than {@link DELETE_DEDUPE_WINDOW_MS} so
|
|
531
|
+
* `recentDeleteEmissions` stays bounded by the number of recent deletes.
|
|
532
|
+
*/
|
|
533
|
+
function pruneRecentDeleteEmissions(now) {
|
|
534
|
+
var _iterator2 = _createForOfIteratorHelper(this.recentDeleteEmissions),
|
|
535
|
+
_step2;
|
|
536
|
+
try {
|
|
537
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
538
|
+
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
539
|
+
resourceId = _step2$value[0],
|
|
540
|
+
emittedAt = _step2$value[1];
|
|
541
|
+
if (now - emittedAt >= DELETE_DEDUPE_WINDOW_MS) {
|
|
542
|
+
this.recentDeleteEmissions.delete(resourceId);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
} catch (err) {
|
|
546
|
+
_iterator2.e(err);
|
|
547
|
+
} finally {
|
|
548
|
+
_iterator2.f();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Emit the `syncedBlockDelete` success event. Gate off: legacy payload. Gate
|
|
554
|
+
* on: attaches `deletionReason`, `mechanism` and `blockInstanceId`, and
|
|
555
|
+
* suppresses repeat emissions within {@link DELETE_DEDUPE_WINDOW_MS}. Must run
|
|
556
|
+
* while the cache entry still exists so `blockInstanceId` is available.
|
|
557
|
+
*/
|
|
558
|
+
}, {
|
|
559
|
+
key: "emitDeleteSuccess",
|
|
560
|
+
value: function emitDeleteSuccess(resourceId, reason, mechanism) {
|
|
561
|
+
var _this$syncBlockCache$2, _this$fireAnalyticsEv9;
|
|
562
|
+
var sourceProduct = getSourceProductFromResourceIdSafe(resourceId);
|
|
563
|
+
if (!fg('platform_editor_blocks_patch_4')) {
|
|
564
|
+
var _this$fireAnalyticsEv8;
|
|
565
|
+
(_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 || _this$fireAnalyticsEv8.call(this, deleteSuccessPayload(resourceId, sourceProduct));
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
var now = Date.now();
|
|
569
|
+
var lastEmittedAt = this.recentDeleteEmissions.get(resourceId);
|
|
570
|
+
if (lastEmittedAt !== undefined && now - lastEmittedAt < DELETE_DEDUPE_WINDOW_MS) {
|
|
571
|
+
return; // duplicate emission for the same logical removal
|
|
572
|
+
}
|
|
573
|
+
this.pruneRecentDeleteEmissions(now);
|
|
574
|
+
this.recentDeleteEmissions.set(resourceId, now);
|
|
575
|
+
var enrichment = {
|
|
576
|
+
blockInstanceId: (_this$syncBlockCache$2 = this.syncBlockCache.get(resourceId)) === null || _this$syncBlockCache$2 === void 0 ? void 0 : _this$syncBlockCache$2.blockInstanceId,
|
|
577
|
+
deletionReason: reason,
|
|
578
|
+
mechanism: mechanism
|
|
579
|
+
};
|
|
580
|
+
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, deleteSuccessPayload(resourceId, sourceProduct, enrichment));
|
|
581
|
+
}
|
|
506
582
|
}, {
|
|
507
583
|
key: "delete",
|
|
508
584
|
value: function () {
|
|
509
|
-
var _delete2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(syncBlockIds, onDelete, onDeleteCompleted, reason) {
|
|
585
|
+
var _delete2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(syncBlockIds, onDelete, onDeleteCompleted, reason, mechanism) {
|
|
510
586
|
var _this5 = this;
|
|
511
587
|
var _this$deleteExperienc, results, callback, isDeleteSuccessful, _this$deleteExperienc2, _this$deleteExperienc3, attributionEnabled, attribution, _t2;
|
|
512
588
|
return _regeneratorRuntime.wrap(function (_context2) {
|
|
@@ -541,15 +617,16 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
541
617
|
onDeleteCompleted(isDeleteSuccessful);
|
|
542
618
|
if (isDeleteSuccessful) {
|
|
543
619
|
onDelete();
|
|
620
|
+
// Emit before the cache entry is deleted below, so blockInstanceId
|
|
621
|
+
// is still available to emitDeleteSuccess.
|
|
622
|
+
results.forEach(function (result) {
|
|
623
|
+
_this5.emitDeleteSuccess(result.resourceId, reason, mechanism);
|
|
624
|
+
});
|
|
544
625
|
callback = function callback(Ids) {
|
|
545
626
|
return _this5.syncBlockCache.delete(Ids.resourceId);
|
|
546
627
|
};
|
|
547
628
|
this.clearPendingDeletion();
|
|
548
629
|
(_this$deleteExperienc2 = this.deleteExperience) === null || _this$deleteExperienc2 === void 0 || _this$deleteExperienc2.success();
|
|
549
|
-
results.forEach(function (result) {
|
|
550
|
-
var _this5$fireAnalyticsE;
|
|
551
|
-
(_this5$fireAnalyticsE = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE === void 0 || _this5$fireAnalyticsE.call(_this5, deleteSuccessPayload(result.resourceId, getSourceProductFromResourceIdSafe(result.resourceId)));
|
|
552
|
-
});
|
|
553
630
|
} else {
|
|
554
631
|
callback = function callback(Ids) {
|
|
555
632
|
_this5.setPendingDeletion(Ids, false);
|
|
@@ -558,11 +635,10 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
558
635
|
attributionEnabled = fg('platform_editor_blocks_patch_3');
|
|
559
636
|
results.forEach(function (result) {
|
|
560
637
|
if (result.success) {
|
|
561
|
-
|
|
562
|
-
(_this5$fireAnalyticsE2 = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE2 === void 0 || _this5$fireAnalyticsE2.call(_this5, deleteSuccessPayload(result.resourceId, getSourceProductFromResourceIdSafe(result.resourceId)));
|
|
638
|
+
_this5.emitDeleteSuccess(result.resourceId, reason, mechanism);
|
|
563
639
|
} else {
|
|
564
|
-
var _this5$
|
|
565
|
-
(_this5$
|
|
640
|
+
var _this5$fireAnalyticsE;
|
|
641
|
+
(_this5$fireAnalyticsE = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE === void 0 || _this5$fireAnalyticsE.call(_this5, deleteErrorPayload(result.error || 'Failed to delete synced block', result.resourceId, getSourceProductFromResourceIdSafe(result.resourceId), buildErrorAttribution(attributionEnabled, result.error, result.statusCode)));
|
|
566
642
|
}
|
|
567
643
|
});
|
|
568
644
|
}
|
|
@@ -575,9 +651,9 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
575
651
|
// so the attribution `reason` falls back to `unknown` when the gate is on.
|
|
576
652
|
attribution = buildErrorAttribution(fg('platform_editor_blocks_patch_3'));
|
|
577
653
|
syncBlockIds.forEach(function (Ids) {
|
|
578
|
-
var _this5$
|
|
654
|
+
var _this5$fireAnalyticsE2;
|
|
579
655
|
_this5.setPendingDeletion(Ids, false);
|
|
580
|
-
(_this5$
|
|
656
|
+
(_this5$fireAnalyticsE2 = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE2 === void 0 || _this5$fireAnalyticsE2.call(_this5, deleteErrorPayload(_t2.message, Ids.resourceId, getSourceProductFromResourceIdSafe(Ids.resourceId), attribution));
|
|
581
657
|
});
|
|
582
658
|
logException(_t2, {
|
|
583
659
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
@@ -590,7 +666,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
590
666
|
}
|
|
591
667
|
}, _callee2, this, [[0, 4]]);
|
|
592
668
|
}));
|
|
593
|
-
function _delete(_x, _x2, _x3, _x4) {
|
|
669
|
+
function _delete(_x, _x2, _x3, _x4, _x5) {
|
|
594
670
|
return _delete2.apply(this, arguments);
|
|
595
671
|
}
|
|
596
672
|
return _delete;
|
|
@@ -604,7 +680,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
604
680
|
key: "retryDeletion",
|
|
605
681
|
value: function () {
|
|
606
682
|
var _retryDeletion = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
607
|
-
var _this$deletionRetryIn, syncBlockIds, onDelete, onDeleteCompleted, deletionReason;
|
|
683
|
+
var _this$deletionRetryIn, syncBlockIds, onDelete, onDeleteCompleted, deletionReason, mechanism;
|
|
608
684
|
return _regeneratorRuntime.wrap(function (_context3) {
|
|
609
685
|
while (1) switch (_context3.prev = _context3.next) {
|
|
610
686
|
case 0:
|
|
@@ -620,13 +696,13 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
620
696
|
}
|
|
621
697
|
return _context3.abrupt("return", Promise.resolve());
|
|
622
698
|
case 2:
|
|
623
|
-
_this$deletionRetryIn = this.deletionRetryInfo, syncBlockIds = _this$deletionRetryIn.syncBlockIds, onDelete = _this$deletionRetryIn.onDelete, onDeleteCompleted = _this$deletionRetryIn.onDeleteCompleted, deletionReason = _this$deletionRetryIn.deletionReason;
|
|
699
|
+
_this$deletionRetryIn = this.deletionRetryInfo, syncBlockIds = _this$deletionRetryIn.syncBlockIds, onDelete = _this$deletionRetryIn.onDelete, onDeleteCompleted = _this$deletionRetryIn.onDeleteCompleted, deletionReason = _this$deletionRetryIn.deletionReason, mechanism = _this$deletionRetryIn.mechanism;
|
|
624
700
|
if (!this.confirmationCallback) {
|
|
625
701
|
_context3.next = 3;
|
|
626
702
|
break;
|
|
627
703
|
}
|
|
628
704
|
_context3.next = 3;
|
|
629
|
-
return this.delete(syncBlockIds, onDelete, onDeleteCompleted, deletionReason);
|
|
705
|
+
return this.delete(syncBlockIds, onDelete, onDeleteCompleted, deletionReason, mechanism);
|
|
630
706
|
case 3:
|
|
631
707
|
case "end":
|
|
632
708
|
return _context3.stop();
|
|
@@ -656,7 +732,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
656
732
|
value: (function () {
|
|
657
733
|
var _fetchAndCacheStatuses = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
|
|
658
734
|
var _this6 = this;
|
|
659
|
-
var sourceToReferenceMap, syncBlockNodes, results,
|
|
735
|
+
var sourceToReferenceMap, syncBlockNodes, results, _iterator3, _step3, _sourceToReferenceMap, _result$data, result, sourceResourceId, cached, _t3;
|
|
660
736
|
return _regeneratorRuntime.wrap(function (_context4) {
|
|
661
737
|
while (1) switch (_context4.prev = _context4.next) {
|
|
662
738
|
case 0:
|
|
@@ -692,10 +768,10 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
692
768
|
return this.dataProvider.fetchNodesData(syncBlockNodes);
|
|
693
769
|
case 3:
|
|
694
770
|
results = _context4.sent;
|
|
695
|
-
|
|
771
|
+
_iterator3 = _createForOfIteratorHelper(results);
|
|
696
772
|
try {
|
|
697
|
-
for (
|
|
698
|
-
result =
|
|
773
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
774
|
+
result = _step3.value;
|
|
699
775
|
// Map the reference resourceId back to the source resourceId
|
|
700
776
|
sourceResourceId = (_sourceToReferenceMap = sourceToReferenceMap.get(result.resourceId)) !== null && _sourceToReferenceMap !== void 0 ? _sourceToReferenceMap : result.resourceId;
|
|
701
777
|
cached = this.syncBlockCache.get(sourceResourceId);
|
|
@@ -704,9 +780,9 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
704
780
|
}
|
|
705
781
|
}
|
|
706
782
|
} catch (err) {
|
|
707
|
-
|
|
783
|
+
_iterator3.e(err);
|
|
708
784
|
} finally {
|
|
709
|
-
|
|
785
|
+
_iterator3.f();
|
|
710
786
|
}
|
|
711
787
|
_context4.next = 5;
|
|
712
788
|
break;
|
|
@@ -756,7 +832,9 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
756
832
|
// onDelete: no-op, document is being discarded
|
|
757
833
|
function () {},
|
|
758
834
|
// onDeleteCompleted: no-op
|
|
759
|
-
'source-block-unpublished'
|
|
835
|
+
'source-block-unpublished',
|
|
836
|
+
// Cancel/discard cleanup is code-initiated, not a direct user edit.
|
|
837
|
+
'other');
|
|
760
838
|
}
|
|
761
839
|
|
|
762
840
|
/**
|
|
@@ -770,7 +848,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
770
848
|
}, {
|
|
771
849
|
key: "deleteSyncBlocksWithConfirmation",
|
|
772
850
|
value: (function () {
|
|
773
|
-
var _deleteSyncBlocksWithConfirmation = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(syncBlockIds, deletionReason, onDelete, onDeleteCompleted, destroyCallback) {
|
|
851
|
+
var _deleteSyncBlocksWithConfirmation = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(syncBlockIds, deletionReason, onDelete, onDeleteCompleted, destroyCallback, mechanism) {
|
|
774
852
|
var confirmed, isDeleteSuccessful;
|
|
775
853
|
return _regeneratorRuntime.wrap(function (_context5) {
|
|
776
854
|
while (1) switch (_context5.prev = _context5.next) {
|
|
@@ -794,7 +872,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
794
872
|
break;
|
|
795
873
|
}
|
|
796
874
|
_context5.next = 3;
|
|
797
|
-
return this.delete(syncBlockIds, onDelete, onDeleteCompleted, deletionReason);
|
|
875
|
+
return this.delete(syncBlockIds, onDelete, onDeleteCompleted, deletionReason, mechanism);
|
|
798
876
|
case 3:
|
|
799
877
|
isDeleteSuccessful = _context5.sent;
|
|
800
878
|
if (!isDeleteSuccessful) {
|
|
@@ -804,7 +882,8 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
804
882
|
onDelete: onDelete,
|
|
805
883
|
onDeleteCompleted: onDeleteCompleted,
|
|
806
884
|
destroyCallback: destroyCallback,
|
|
807
|
-
deletionReason: deletionReason
|
|
885
|
+
deletionReason: deletionReason,
|
|
886
|
+
mechanism: mechanism
|
|
808
887
|
};
|
|
809
888
|
} else {
|
|
810
889
|
destroyCallback();
|
|
@@ -819,7 +898,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
819
898
|
}
|
|
820
899
|
}, _callee5, this);
|
|
821
900
|
}));
|
|
822
|
-
function deleteSyncBlocksWithConfirmation(
|
|
901
|
+
function deleteSyncBlocksWithConfirmation(_x6, _x7, _x8, _x9, _x0, _x1) {
|
|
823
902
|
return _deleteSyncBlocksWithConfirmation.apply(this, arguments);
|
|
824
903
|
}
|
|
825
904
|
return deleteSyncBlocksWithConfirmation;
|
|
@@ -847,11 +926,11 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
847
926
|
return sourceInfo;
|
|
848
927
|
});
|
|
849
928
|
} catch (error) {
|
|
850
|
-
var _this$
|
|
929
|
+
var _this$fireAnalyticsEv0;
|
|
851
930
|
logException(error, {
|
|
852
931
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
853
932
|
});
|
|
854
|
-
(_this$
|
|
933
|
+
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, getSourceInfoErrorPayload(error.message));
|
|
855
934
|
return Promise.resolve(undefined);
|
|
856
935
|
}
|
|
857
936
|
}
|
|
@@ -864,11 +943,11 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
864
943
|
}
|
|
865
944
|
return this.dataProvider.fetchReferences(resourceId, true);
|
|
866
945
|
} catch (error) {
|
|
867
|
-
var _this$
|
|
946
|
+
var _this$fireAnalyticsEv1;
|
|
868
947
|
logException(error, {
|
|
869
948
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
870
949
|
});
|
|
871
|
-
(_this$
|
|
950
|
+
(_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 || _this$fireAnalyticsEv1.call(this, fetchReferencesErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
872
951
|
return Promise.resolve({
|
|
873
952
|
error: SyncBlockError.Errored
|
|
874
953
|
});
|
|
@@ -885,6 +964,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
885
964
|
this.postCreationFlushCallback = undefined;
|
|
886
965
|
this.pendingCreationPromises.clear();
|
|
887
966
|
this.creationsTimedOutDuringFlush.clear();
|
|
967
|
+
this.recentDeleteEmissions.clear();
|
|
888
968
|
this.dataProvider = undefined;
|
|
889
969
|
(_this$saveExperience4 = this.saveExperience) === null || _this$saveExperience4 === void 0 || _this$saveExperience4.abort({
|
|
890
970
|
reason: 'editorDestroyed'
|
|
@@ -325,15 +325,25 @@ export var createSuccessPayload = function createSuccessPayload(resourceId, sour
|
|
|
325
325
|
})
|
|
326
326
|
};
|
|
327
327
|
};
|
|
328
|
-
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Operational `syncedBlockCreate` success event (previously only error rows
|
|
331
|
+
* existed, so dashboards had no create denominator). Fired behind
|
|
332
|
+
* `platform_editor_blocks_patch_4` with the `blockInstanceId` join key.
|
|
333
|
+
*/
|
|
334
|
+
export var createSuccessPayloadNew = function createSuccessPayloadNew(resourceId, blockInstanceId, sourceProduct) {
|
|
329
335
|
return {
|
|
330
336
|
action: ACTION.INSERTED,
|
|
331
337
|
actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
|
|
332
338
|
actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE,
|
|
333
339
|
eventType: EVENT_TYPE.OPERATIONAL,
|
|
334
|
-
attributes: {
|
|
340
|
+
attributes: _objectSpread(_objectSpread({
|
|
335
341
|
resourceId: resourceId
|
|
336
|
-
}
|
|
342
|
+
}, blockInstanceId && {
|
|
343
|
+
blockInstanceId: blockInstanceId
|
|
344
|
+
}), sourceProduct && {
|
|
345
|
+
sourceProduct: sourceProduct
|
|
346
|
+
})
|
|
337
347
|
};
|
|
338
348
|
};
|
|
339
349
|
export var updateSuccessPayload = function updateSuccessPayload(resourceId, hasReference, sourceProduct) {
|
|
@@ -351,16 +361,29 @@ export var updateSuccessPayload = function updateSuccessPayload(resourceId, hasR
|
|
|
351
361
|
})
|
|
352
362
|
};
|
|
353
363
|
};
|
|
354
|
-
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Optional enrichment for the `syncedBlockDelete` success event behind
|
|
367
|
+
* `platform_editor_blocks_patch_4`. All fields optional so the gate-off payload
|
|
368
|
+
* is unchanged; `blockInstanceId` is the bare-uuid join key.
|
|
369
|
+
*/
|
|
370
|
+
|
|
371
|
+
export var deleteSuccessPayload = function deleteSuccessPayload(resourceId, sourceProduct, enrichment) {
|
|
355
372
|
return {
|
|
356
373
|
action: ACTION.DELETED,
|
|
357
374
|
actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
|
|
358
375
|
actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_DELETE,
|
|
359
376
|
eventType: EVENT_TYPE.OPERATIONAL,
|
|
360
|
-
attributes: _objectSpread({
|
|
377
|
+
attributes: _objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
361
378
|
resourceId: resourceId
|
|
362
379
|
}, sourceProduct && {
|
|
363
380
|
sourceProduct: sourceProduct
|
|
381
|
+
}), (enrichment === null || enrichment === void 0 ? void 0 : enrichment.blockInstanceId) && {
|
|
382
|
+
blockInstanceId: enrichment.blockInstanceId
|
|
383
|
+
}), (enrichment === null || enrichment === void 0 ? void 0 : enrichment.deletionReason) && {
|
|
384
|
+
deletionReason: enrichment.deletionReason
|
|
385
|
+
}), (enrichment === null || enrichment === void 0 ? void 0 : enrichment.mechanism) && {
|
|
386
|
+
mechanism: enrichment.mechanism
|
|
364
387
|
})
|
|
365
388
|
};
|
|
366
389
|
};
|
|
@@ -76,6 +76,21 @@ export type ReferencesSourceInfo = {
|
|
|
76
76
|
};
|
|
77
77
|
export type DeletionReason = 'source-block-deleted' | 'source-block-unsynced' | 'source-block-unpublished';
|
|
78
78
|
export type DeletionReasonResponse = DeletionReason | 'source-document-deleted';
|
|
79
|
+
/**
|
|
80
|
+
* How a source bodiedSyncBlock removal was performed, derived from the
|
|
81
|
+
* originating transaction. Distinct from {@link DeletionReason} (the outcome):
|
|
82
|
+
* `mechanism` tells deliberate deletes apart from undos and accidental overwrites.
|
|
83
|
+
*
|
|
84
|
+
* Values name the user action that produced the removal:
|
|
85
|
+
* - `undo` / `redo` — removal came from a history undo/redo.
|
|
86
|
+
* - `deleteButton` — the explicit "Delete" control in the synced-block toolbar.
|
|
87
|
+
* - `keyboardDelete` — Backspace/Delete key on a caret or range selection.
|
|
88
|
+
* - `selectionReplaced` — the block was selected and replaced by typing or
|
|
89
|
+
* pasting over it (the accidental-overwrite path).
|
|
90
|
+
* - `other` — any non-direct removal (unsync, conversion, code-dispatched, or a
|
|
91
|
+
* structural wrap/lift/unwrap edit).
|
|
92
|
+
*/
|
|
93
|
+
export type DeletionMechanism = 'undo' | 'redo' | 'deleteButton' | 'keyboardDelete' | 'selectionReplaced' | 'other';
|
|
79
94
|
export type SyncBlockPrefetchData = {
|
|
80
95
|
prefetchPromise: Promise<SyncBlockInstance[] | undefined>;
|
|
81
96
|
resourceIds: string[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { SyncBlockError } from '../common/types';
|
|
2
|
-
export type { ResourceId, SyncBlockData, SyncBlockNode, SyncBlockProduct, SyncBlockStatus, BlockInstanceId, SyncBlockAttrs, ReferenceSyncBlockData, ReferencesSourceInfo, DeletionReason, SyncBlockPrefetchData, } from '../common/types';
|
|
2
|
+
export type { ResourceId, SyncBlockData, SyncBlockNode, SyncBlockProduct, SyncBlockStatus, BlockInstanceId, SyncBlockAttrs, ReferenceSyncBlockData, ReferencesSourceInfo, DeletionReason, DeletionMechanism, SyncBlockPrefetchData, } from '../common/types';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SyncBlockEventPayload } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import type { ViewMode } from '@atlaskit/editor-plugin-editor-viewmode';
|
|
3
3
|
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
4
|
-
import type { ResourceId, SyncBlockAttrs, BlockInstanceId, DeletionReason, ReferenceSyncBlockData } from '../common/types';
|
|
4
|
+
import type { ResourceId, SyncBlockAttrs, BlockInstanceId, DeletionReason, DeletionMechanism, ReferenceSyncBlockData } from '../common/types';
|
|
5
5
|
import type { SyncBlockDataProviderInterface, SyncBlockSourceInfo } from '../providers/types';
|
|
6
6
|
export type ConfirmationCallback = (syncBlockIds: SyncBlockAttrs[], deleteReason: DeletionReason | undefined) => Promise<boolean>;
|
|
7
7
|
type OnDelete = () => void;
|
|
@@ -39,6 +39,12 @@ export declare class SourceSyncBlockStoreManager {
|
|
|
39
39
|
private saveExperience;
|
|
40
40
|
private deleteExperience;
|
|
41
41
|
private fetchSourceInfoExperience;
|
|
42
|
+
/**
|
|
43
|
+
* resourceId -> timestamp (ms) of the last `syncedBlockDelete` emission, used
|
|
44
|
+
* to suppress duplicates within {@link DELETE_DEDUPE_WINDOW_MS}. Only consulted
|
|
45
|
+
* behind `platform_editor_blocks_patch_4`.
|
|
46
|
+
*/
|
|
47
|
+
private recentDeleteEmissions;
|
|
42
48
|
constructor(dataProvider?: SyncBlockDataProviderInterface, viewMode?: ViewMode, isLivePage?: boolean);
|
|
43
49
|
/**
|
|
44
50
|
* Register a callback to be invoked after flush() completes.
|
|
@@ -94,6 +100,18 @@ export declare class SourceSyncBlockStoreManager {
|
|
|
94
100
|
*/
|
|
95
101
|
createBodiedSyncBlockNode(attrs: SyncBlockAttrs, node: PMNode, onCompletion: OnCompletion): void;
|
|
96
102
|
private setPendingDeletion;
|
|
103
|
+
/**
|
|
104
|
+
* Drop dedupe entries older than {@link DELETE_DEDUPE_WINDOW_MS} so
|
|
105
|
+
* `recentDeleteEmissions` stays bounded by the number of recent deletes.
|
|
106
|
+
*/
|
|
107
|
+
private pruneRecentDeleteEmissions;
|
|
108
|
+
/**
|
|
109
|
+
* Emit the `syncedBlockDelete` success event. Gate off: legacy payload. Gate
|
|
110
|
+
* on: attaches `deletionReason`, `mechanism` and `blockInstanceId`, and
|
|
111
|
+
* suppresses repeat emissions within {@link DELETE_DEDUPE_WINDOW_MS}. Must run
|
|
112
|
+
* while the cache entry still exists so `blockInstanceId` is available.
|
|
113
|
+
*/
|
|
114
|
+
private emitDeleteSuccess;
|
|
97
115
|
private delete;
|
|
98
116
|
isRetryingDeletion(): boolean;
|
|
99
117
|
retryDeletion(): Promise<void>;
|
|
@@ -120,7 +138,7 @@ export declare class SourceSyncBlockStoreManager {
|
|
|
120
138
|
* @param onDeleteCompleted - The callback for after the deletion is saved to BE (whether successful or not)
|
|
121
139
|
* @param destroyCallback - The callback to clear any reference stored for deletion (regardless if deletion is completed or abort)
|
|
122
140
|
*/
|
|
123
|
-
deleteSyncBlocksWithConfirmation(syncBlockIds: SyncBlockAttrs[], deletionReason: DeletionReason, onDelete: OnDelete, onDeleteCompleted: OnCompletion, destroyCallback: DestroyCallback): Promise<void>;
|
|
141
|
+
deleteSyncBlocksWithConfirmation(syncBlockIds: SyncBlockAttrs[], deletionReason: DeletionReason, onDelete: OnDelete, onDeleteCompleted: OnCompletion, destroyCallback: DestroyCallback, mechanism?: DeletionMechanism): Promise<void>;
|
|
124
142
|
getSyncBlockSourceInfo(localId: BlockInstanceId): Promise<SyncBlockSourceInfo | undefined>;
|
|
125
143
|
fetchReferences(resourceId: string): Promise<ReferenceSyncBlockData>;
|
|
126
144
|
destroy(): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import type { RendererSyncBlockEventPayload, OperationalAEP, SyncBlockEventPayload } from '@atlaskit/editor-common/analytics';
|
|
3
3
|
import { SyncBlockError } from '../common/types';
|
|
4
|
+
import type { DeletionMechanism, DeletionReason } from '../common/types';
|
|
4
5
|
export declare const stringifyError: (error: unknown) => string | undefined;
|
|
5
6
|
/**
|
|
6
7
|
* The set of categorical failure reasons emitted on synced-block operational error
|
|
@@ -162,6 +163,21 @@ export declare const cacheDeletionForcedPayload: (rescheduleCount: number, resou
|
|
|
162
163
|
export declare const fetchReferencesErrorPayload: (error: string, resourceId?: string, sourceProduct?: string) => SyncBlockEventPayload;
|
|
163
164
|
export declare const fetchSuccessPayload: (resourceId: string, blockInstanceId?: string, sourceProduct?: string) => RendererSyncBlockEventPayload;
|
|
164
165
|
export declare const createSuccessPayload: (resourceId: string, sourceProduct?: string) => SyncBlockEventPayload;
|
|
165
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Operational `syncedBlockCreate` success event (previously only error rows
|
|
168
|
+
* existed, so dashboards had no create denominator). Fired behind
|
|
169
|
+
* `platform_editor_blocks_patch_4` with the `blockInstanceId` join key.
|
|
170
|
+
*/
|
|
171
|
+
export declare const createSuccessPayloadNew: (resourceId: string, blockInstanceId?: string, sourceProduct?: string) => SyncBlockEventPayload;
|
|
166
172
|
export declare const updateSuccessPayload: (resourceId: string, hasReference?: boolean, sourceProduct?: string) => SyncBlockEventPayload;
|
|
167
|
-
|
|
173
|
+
/**
|
|
174
|
+
* Optional enrichment for the `syncedBlockDelete` success event behind
|
|
175
|
+
* `platform_editor_blocks_patch_4`. All fields optional so the gate-off payload
|
|
176
|
+
* is unchanged; `blockInstanceId` is the bare-uuid join key.
|
|
177
|
+
*/
|
|
178
|
+
export type DeleteSuccessEnrichment = {
|
|
179
|
+
blockInstanceId?: string;
|
|
180
|
+
deletionReason?: DeletionReason;
|
|
181
|
+
mechanism?: DeletionMechanism;
|
|
182
|
+
};
|
|
183
|
+
export declare const deleteSuccessPayload: (resourceId: string, sourceProduct?: string, enrichment?: DeleteSuccessEnrichment) => SyncBlockEventPayload;
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@atlaskit/editor-prosemirror": "^8.0.0",
|
|
22
22
|
"@atlaskit/node-data-provider": "^13.0.0",
|
|
23
23
|
"@atlaskit/platform-feature-flags": "^2.0.0",
|
|
24
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
24
|
+
"@atlaskit/tmp-editor-statsig": "^119.0.0",
|
|
25
25
|
"@babel/runtime": "^7.0.0",
|
|
26
26
|
"@compiled/react": "^0.20.0",
|
|
27
27
|
"graphql-ws": "^5.14.2",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"uuid": "^3.1.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@atlaskit/editor-common": "^116.
|
|
33
|
+
"@atlaskit/editor-common": "^116.19.0",
|
|
34
34
|
"react": "^18.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
"name": "@atlaskit/editor-synced-block-provider",
|
|
77
|
-
"version": "8.
|
|
77
|
+
"version": "8.5.1",
|
|
78
78
|
"description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
|
|
79
79
|
"author": "Atlassian Pty Ltd",
|
|
80
80
|
"license": "Apache-2.0",
|