@atlaskit/editor-synced-block-provider 6.6.7 → 6.6.9
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 +19 -0
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +101 -9
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +91 -4
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +101 -9
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +9 -0
- package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +9 -0
- package/package.json +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-synced-block-provider
|
|
2
2
|
|
|
3
|
+
## 6.6.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`085a281306c03`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/085a281306c03) -
|
|
8
|
+
Add defensive mechanisms for synced block EntityNotFound errors:
|
|
9
|
+
- Add retry with exponential backoff when fetching synced block references returns EntityNotFound
|
|
10
|
+
(up to 3 retries with 2s/4s/8s delays)
|
|
11
|
+
- Add transformPasted handler to convert any bodiedSyncBlock nodes arriving via paste into
|
|
12
|
+
syncBlock references, preventing createBlock from being called with the wrong parentId
|
|
13
|
+
|
|
14
|
+
Both changes are gated behind `platform_synced_block_patch_13`.
|
|
15
|
+
|
|
16
|
+
## 6.6.8
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 6.6.7
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -29,6 +29,8 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
29
29
|
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; }
|
|
30
30
|
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) { (0, _defineProperty2.default)(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; }
|
|
31
31
|
var CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
32
|
+
var ENTITY_NOT_FOUND_MAX_RETRIES = 3;
|
|
33
|
+
var ENTITY_NOT_FOUND_INITIAL_DELAY_MS = 2000;
|
|
32
34
|
|
|
33
35
|
// A store manager responsible for the lifecycle and state management of reference sync blocks in an editor instance.
|
|
34
36
|
// Designed to manage local in-memory state and synchronize with an external data provider.
|
|
@@ -36,8 +38,6 @@ var CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
|
36
38
|
// Handles fetching source URL and title for sync blocks.
|
|
37
39
|
// Can be used in both editor and renderer contexts.
|
|
38
40
|
var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
39
|
-
// Track the setTimeout handle for queued flush so we can cancel it on destroy
|
|
40
|
-
|
|
41
41
|
function ReferenceSyncBlockStoreManager(dataProvider, viewMode) {
|
|
42
42
|
var _this = this,
|
|
43
43
|
_this$dataProvider;
|
|
@@ -52,6 +52,9 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
52
52
|
(0, _defineProperty2.default)(this, "isFlushInProgress", false);
|
|
53
53
|
// Track if another flush is needed after the current one completes
|
|
54
54
|
(0, _defineProperty2.default)(this, "flushNeededAfterCurrent", false);
|
|
55
|
+
// Track retry attempts for EntityNotFound errors (block may be in the process of being created)
|
|
56
|
+
(0, _defineProperty2.default)(this, "entityNotFoundRetryCount", new Map());
|
|
57
|
+
(0, _defineProperty2.default)(this, "entityNotFoundRetryTimers", new Map());
|
|
55
58
|
this.dataProvider = dataProvider;
|
|
56
59
|
this.viewMode = viewMode;
|
|
57
60
|
this.syncBlockFetchDataRequests = new Map();
|
|
@@ -211,6 +214,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
211
214
|
var syncBlockNode = (0, _utils.createSyncBlockNode)('', resourceId);
|
|
212
215
|
var providerData = (_this$dataProvider2 = this.dataProvider) === null || _this$dataProvider2 === void 0 || (_this$dataProvider2 = _this$dataProvider2.getNodeDataFromCache(syncBlockNode)) === null || _this$dataProvider2 === void 0 ? void 0 : _this$dataProvider2.data;
|
|
213
216
|
if (providerData) {
|
|
217
|
+
// Initial provider cache data can come from SSR/prefetch and bypass updateCache(),
|
|
218
|
+
// so strip annotations here before references render existing synced block payloads.
|
|
214
219
|
return this.stripAnnotationMarksFromReferenceData(providerData);
|
|
215
220
|
}
|
|
216
221
|
return this.getFromSessionCache(resourceId);
|
|
@@ -248,6 +253,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
248
253
|
if (!raw) {
|
|
249
254
|
return undefined;
|
|
250
255
|
}
|
|
256
|
+
// Session cache entries written before this sanitizer existed may still include
|
|
257
|
+
// source annotation marks, so keep this read-time safety net for legacy data.
|
|
251
258
|
return this.stripAnnotationMarksFromReferenceData(JSON.parse(raw));
|
|
252
259
|
} catch (error) {
|
|
253
260
|
(0, _monitoring.logException)(error, {
|
|
@@ -577,11 +584,37 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
577
584
|
// Remove from newly added set even if not unpublished (to clean up)
|
|
578
585
|
_this5.newlyAddedSyncBlocks.delete(syncBlockInstance.resourceId);
|
|
579
586
|
}
|
|
587
|
+
|
|
588
|
+
// Clear retry tracking on successful fetch — block has been created
|
|
589
|
+
if (!syncBlockInstance.error && _this5.entityNotFoundRetryCount.has(syncBlockInstance.resourceId)) {
|
|
590
|
+
var timer = _this5.entityNotFoundRetryTimers.get(syncBlockInstance.resourceId);
|
|
591
|
+
if (timer) {
|
|
592
|
+
clearTimeout(timer);
|
|
593
|
+
_this5.entityNotFoundRetryTimers.delete(syncBlockInstance.resourceId);
|
|
594
|
+
}
|
|
595
|
+
_this5.entityNotFoundRetryCount.delete(syncBlockInstance.resourceId);
|
|
596
|
+
}
|
|
580
597
|
if (syncBlockInstance.error) {
|
|
581
|
-
var _this5$
|
|
582
|
-
|
|
598
|
+
var _this5$entityNotFound;
|
|
599
|
+
// Skip error analytics when EntityNotFound will be retried, to avoid
|
|
600
|
+
// inflating error-rate metrics with expected transient failures
|
|
601
|
+
var isRetryingEntityNotFound = syncBlockInstance.error.type === _types.SyncBlockError.EntityNotFound && ((_this5$entityNotFound = _this5.entityNotFoundRetryCount.get(syncBlockInstance.resourceId)) !== null && _this5$entityNotFound !== void 0 ? _this5$entityNotFound : 0) < ENTITY_NOT_FOUND_MAX_RETRIES && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_13');
|
|
602
|
+
if (!isRetryingEntityNotFound) {
|
|
603
|
+
var _this5$fireAnalyticsE2, _syncBlockInstance$da, _syncBlockInstance$da2;
|
|
604
|
+
(_this5$fireAnalyticsE2 = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE2 === void 0 || _this5$fireAnalyticsE2.call(_this5, (0, _errorHandling.fetchErrorPayload)(syncBlockInstance.error.reason || syncBlockInstance.error.type, syncBlockInstance.resourceId, (_syncBlockInstance$da = (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product) !== null && _syncBlockInstance$da !== void 0 ? _syncBlockInstance$da : (0, _utils.getSourceProductFromResourceIdSafe)(syncBlockInstance.resourceId)));
|
|
605
|
+
}
|
|
583
606
|
if (syncBlockInstance.error.type === _types.SyncBlockError.NotFound || syncBlockInstance.error.type === _types.SyncBlockError.Forbidden) {
|
|
584
607
|
hasExpectedError = true;
|
|
608
|
+
} else if (syncBlockInstance.error.type === _types.SyncBlockError.EntityNotFound) {
|
|
609
|
+
// Schedule a retry for EntityNotFound — the source block may be in
|
|
610
|
+
// the process of being created by a collaborator (race condition
|
|
611
|
+
// between NCS propagation and Block Service createBlock call).
|
|
612
|
+
if ((0, _platformFeatureFlags.fg)('platform_synced_block_patch_13')) {
|
|
613
|
+
_this5.scheduleEntityNotFoundRetry(syncBlockInstance.resourceId);
|
|
614
|
+
}
|
|
615
|
+
if (!isRetryingEntityNotFound) {
|
|
616
|
+
hasUnexpectedError = true;
|
|
617
|
+
}
|
|
585
618
|
} else if (syncBlockInstance.error) {
|
|
586
619
|
hasUnexpectedError = true;
|
|
587
620
|
}
|
|
@@ -645,6 +678,58 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
645
678
|
(_this$dataProvider5 = this.dataProvider) === null || _this$dataProvider5 === void 0 || _this$dataProvider5.removeFromCache([resourceId]);
|
|
646
679
|
this._providerFactoryManager.deleteFactory(resourceId);
|
|
647
680
|
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Schedules a delayed retry for a block that returned EntityNotFound.
|
|
684
|
+
* The block may be in the process of being created by a collaborator —
|
|
685
|
+
* the NCS transaction propagates the bodiedSyncBlock ADF node before
|
|
686
|
+
* the Block Service createBlock call completes.
|
|
687
|
+
*/
|
|
688
|
+
}, {
|
|
689
|
+
key: "scheduleEntityNotFoundRetry",
|
|
690
|
+
value: function scheduleEntityNotFoundRetry(resourceId) {
|
|
691
|
+
var _this$entityNotFoundR,
|
|
692
|
+
_this6 = this;
|
|
693
|
+
var currentRetries = (_this$entityNotFoundR = this.entityNotFoundRetryCount.get(resourceId)) !== null && _this$entityNotFoundR !== void 0 ? _this$entityNotFoundR : 0;
|
|
694
|
+
if (currentRetries >= ENTITY_NOT_FOUND_MAX_RETRIES) {
|
|
695
|
+
// Max retries exceeded — keep count at max so future calls immediately exit
|
|
696
|
+
// (don't delete — that would reset the counter and allow unbounded retry waves)
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// If a timer is already pending, don't schedule another one — let the
|
|
701
|
+
// existing timer fire. This prevents rapid EntityNotFound responses from
|
|
702
|
+
// exhausting the retry budget through cancellations without any actual
|
|
703
|
+
// fetch completing.
|
|
704
|
+
if (this.entityNotFoundRetryTimers.has(resourceId)) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
var delay = ENTITY_NOT_FOUND_INITIAL_DELAY_MS * Math.pow(2, currentRetries);
|
|
708
|
+
var timer = setTimeout(function () {
|
|
709
|
+
var _cached$error;
|
|
710
|
+
_this6.entityNotFoundRetryTimers.delete(resourceId);
|
|
711
|
+
|
|
712
|
+
// If no active subscriptions remain for this block, clean up and skip
|
|
713
|
+
var subscriptions = _this6._subscriptionManager.getSubscriptions().get(resourceId);
|
|
714
|
+
if (!subscriptions || Object.keys(subscriptions).length === 0) {
|
|
715
|
+
_this6.entityNotFoundRetryCount.delete(resourceId);
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Increment count only when the timer fires, not when scheduled
|
|
720
|
+
_this6.entityNotFoundRetryCount.set(resourceId, currentRetries + 1);
|
|
721
|
+
|
|
722
|
+
// Clear the error from cache so fetchSyncBlocksData doesn't skip it
|
|
723
|
+
var cached = _this6.getFromCache(resourceId);
|
|
724
|
+
if ((cached === null || cached === void 0 || (_cached$error = cached.error) === null || _cached$error === void 0 ? void 0 : _cached$error.type) === _types.SyncBlockError.EntityNotFound) {
|
|
725
|
+
_this6.deleteFromCache(resourceId);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Trigger a re-fetch via the batch fetcher
|
|
729
|
+
_this6.debouncedBatchedFetchSyncBlocks(resourceId);
|
|
730
|
+
}, delay);
|
|
731
|
+
this.entityNotFoundRetryTimers.set(resourceId, timer);
|
|
732
|
+
}
|
|
648
733
|
}, {
|
|
649
734
|
key: "debouncedBatchedFetchSyncBlocks",
|
|
650
735
|
value: function debouncedBatchedFetchSyncBlocks(resourceId) {
|
|
@@ -653,12 +738,12 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
653
738
|
}, {
|
|
654
739
|
key: "setSSRDataInSessionCache",
|
|
655
740
|
value: function setSSRDataInSessionCache(resourceIds) {
|
|
656
|
-
var
|
|
741
|
+
var _this7 = this;
|
|
657
742
|
if (!resourceIds || resourceIds.length === 0) {
|
|
658
743
|
return;
|
|
659
744
|
}
|
|
660
745
|
resourceIds.forEach(function (resourceId) {
|
|
661
|
-
|
|
746
|
+
_this7.updateSessionCache(resourceId);
|
|
662
747
|
});
|
|
663
748
|
}
|
|
664
749
|
}, {
|
|
@@ -731,7 +816,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
731
816
|
key: "flush",
|
|
732
817
|
value: (function () {
|
|
733
818
|
var _flush = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
734
|
-
var
|
|
819
|
+
var _this8 = this;
|
|
735
820
|
var success, syncedBlocksToFlush, _this$saveExperience, blocks, _iterator, _step, _loop, updateResult, _this$saveExperience2, _this$fireAnalyticsEv6, _this$saveExperience3, _this$fireAnalyticsEv7, _this$saveExperience4;
|
|
736
821
|
return _regenerator.default.wrap(function _callee3$(_context4) {
|
|
737
822
|
while (1) switch (_context4.prev = _context4.next) {
|
|
@@ -873,8 +958,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
873
958
|
// Use setTimeout to avoid deep recursion and run queued flush asynchronously
|
|
874
959
|
// Note: flush() handles all exceptions internally and never rejects
|
|
875
960
|
this.queuedFlushTimeout = setTimeout(function () {
|
|
876
|
-
|
|
877
|
-
void
|
|
961
|
+
_this8.queuedFlushTimeout = undefined;
|
|
962
|
+
void _this8.flush();
|
|
878
963
|
}, 0);
|
|
879
964
|
}
|
|
880
965
|
return _context4.finish(49);
|
|
@@ -900,6 +985,13 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
900
985
|
clearTimeout(this.queuedFlushTimeout);
|
|
901
986
|
this.queuedFlushTimeout = undefined;
|
|
902
987
|
}
|
|
988
|
+
|
|
989
|
+
// Cancel any pending EntityNotFound retry timers
|
|
990
|
+
this.entityNotFoundRetryTimers.forEach(function (timer) {
|
|
991
|
+
return clearTimeout(timer);
|
|
992
|
+
});
|
|
993
|
+
this.entityNotFoundRetryTimers.clear();
|
|
994
|
+
this.entityNotFoundRetryCount.clear();
|
|
903
995
|
this._subscriptionManager.destroy();
|
|
904
996
|
this._providerFactoryManager.destroy();
|
|
905
997
|
this._batchFetcher.destroy();
|
|
@@ -12,6 +12,8 @@ import { syncBlockInMemorySessionCache } from './syncBlockInMemorySessionCache';
|
|
|
12
12
|
import { SyncBlockProviderFactoryManager } from './syncBlockProviderFactoryManager';
|
|
13
13
|
import { SyncBlockSubscriptionManager } from './syncBlockSubscriptionManager';
|
|
14
14
|
const CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
15
|
+
const ENTITY_NOT_FOUND_MAX_RETRIES = 3;
|
|
16
|
+
const ENTITY_NOT_FOUND_INITIAL_DELAY_MS = 2000;
|
|
15
17
|
|
|
16
18
|
// A store manager responsible for the lifecycle and state management of reference sync blocks in an editor instance.
|
|
17
19
|
// Designed to manage local in-memory state and synchronize with an external data provider.
|
|
@@ -19,8 +21,6 @@ const CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
|
19
21
|
// Handles fetching source URL and title for sync blocks.
|
|
20
22
|
// Can be used in both editor and renderer contexts.
|
|
21
23
|
export class ReferenceSyncBlockStoreManager {
|
|
22
|
-
// Track the setTimeout handle for queued flush so we can cancel it on destroy
|
|
23
|
-
|
|
24
24
|
constructor(dataProvider, viewMode) {
|
|
25
25
|
var _this$dataProvider;
|
|
26
26
|
// Keeps track of addition and deletion of reference synced blocks on the document
|
|
@@ -33,6 +33,9 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
33
33
|
_defineProperty(this, "isFlushInProgress", false);
|
|
34
34
|
// Track if another flush is needed after the current one completes
|
|
35
35
|
_defineProperty(this, "flushNeededAfterCurrent", false);
|
|
36
|
+
// Track retry attempts for EntityNotFound errors (block may be in the process of being created)
|
|
37
|
+
_defineProperty(this, "entityNotFoundRetryCount", new Map());
|
|
38
|
+
_defineProperty(this, "entityNotFoundRetryTimers", new Map());
|
|
36
39
|
this.dataProvider = dataProvider;
|
|
37
40
|
this.viewMode = viewMode;
|
|
38
41
|
this.syncBlockFetchDataRequests = new Map();
|
|
@@ -142,6 +145,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
142
145
|
const syncBlockNode = createSyncBlockNode('', resourceId);
|
|
143
146
|
const providerData = (_this$dataProvider2 = this.dataProvider) === null || _this$dataProvider2 === void 0 ? void 0 : (_this$dataProvider2$g = _this$dataProvider2.getNodeDataFromCache(syncBlockNode)) === null || _this$dataProvider2$g === void 0 ? void 0 : _this$dataProvider2$g.data;
|
|
144
147
|
if (providerData) {
|
|
148
|
+
// Initial provider cache data can come from SSR/prefetch and bypass updateCache(),
|
|
149
|
+
// so strip annotations here before references render existing synced block payloads.
|
|
145
150
|
return this.stripAnnotationMarksFromReferenceData(providerData);
|
|
146
151
|
}
|
|
147
152
|
return this.getFromSessionCache(resourceId);
|
|
@@ -175,6 +180,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
175
180
|
if (!raw) {
|
|
176
181
|
return undefined;
|
|
177
182
|
}
|
|
183
|
+
// Session cache entries written before this sanitizer existed may still include
|
|
184
|
+
// source annotation marks, so keep this read-time safety net for legacy data.
|
|
178
185
|
return this.stripAnnotationMarksFromReferenceData(JSON.parse(raw));
|
|
179
186
|
} catch (error) {
|
|
180
187
|
logException(error, {
|
|
@@ -449,11 +456,37 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
449
456
|
// Remove from newly added set even if not unpublished (to clean up)
|
|
450
457
|
this.newlyAddedSyncBlocks.delete(syncBlockInstance.resourceId);
|
|
451
458
|
}
|
|
459
|
+
|
|
460
|
+
// Clear retry tracking on successful fetch — block has been created
|
|
461
|
+
if (!syncBlockInstance.error && this.entityNotFoundRetryCount.has(syncBlockInstance.resourceId)) {
|
|
462
|
+
const timer = this.entityNotFoundRetryTimers.get(syncBlockInstance.resourceId);
|
|
463
|
+
if (timer) {
|
|
464
|
+
clearTimeout(timer);
|
|
465
|
+
this.entityNotFoundRetryTimers.delete(syncBlockInstance.resourceId);
|
|
466
|
+
}
|
|
467
|
+
this.entityNotFoundRetryCount.delete(syncBlockInstance.resourceId);
|
|
468
|
+
}
|
|
452
469
|
if (syncBlockInstance.error) {
|
|
453
|
-
var _this$
|
|
454
|
-
|
|
470
|
+
var _this$entityNotFoundR;
|
|
471
|
+
// Skip error analytics when EntityNotFound will be retried, to avoid
|
|
472
|
+
// inflating error-rate metrics with expected transient failures
|
|
473
|
+
const isRetryingEntityNotFound = syncBlockInstance.error.type === SyncBlockError.EntityNotFound && ((_this$entityNotFoundR = this.entityNotFoundRetryCount.get(syncBlockInstance.resourceId)) !== null && _this$entityNotFoundR !== void 0 ? _this$entityNotFoundR : 0) < ENTITY_NOT_FOUND_MAX_RETRIES && fg('platform_synced_block_patch_13');
|
|
474
|
+
if (!isRetryingEntityNotFound) {
|
|
475
|
+
var _this$fireAnalyticsEv9, _syncBlockInstance$da, _syncBlockInstance$da2;
|
|
476
|
+
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, fetchErrorPayload(syncBlockInstance.error.reason || syncBlockInstance.error.type, syncBlockInstance.resourceId, (_syncBlockInstance$da = (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product) !== null && _syncBlockInstance$da !== void 0 ? _syncBlockInstance$da : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId)));
|
|
477
|
+
}
|
|
455
478
|
if (syncBlockInstance.error.type === SyncBlockError.NotFound || syncBlockInstance.error.type === SyncBlockError.Forbidden) {
|
|
456
479
|
hasExpectedError = true;
|
|
480
|
+
} else if (syncBlockInstance.error.type === SyncBlockError.EntityNotFound) {
|
|
481
|
+
// Schedule a retry for EntityNotFound — the source block may be in
|
|
482
|
+
// the process of being created by a collaborator (race condition
|
|
483
|
+
// between NCS propagation and Block Service createBlock call).
|
|
484
|
+
if (fg('platform_synced_block_patch_13')) {
|
|
485
|
+
this.scheduleEntityNotFoundRetry(syncBlockInstance.resourceId);
|
|
486
|
+
}
|
|
487
|
+
if (!isRetryingEntityNotFound) {
|
|
488
|
+
hasUnexpectedError = true;
|
|
489
|
+
}
|
|
457
490
|
} else if (syncBlockInstance.error) {
|
|
458
491
|
hasUnexpectedError = true;
|
|
459
492
|
}
|
|
@@ -514,6 +547,55 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
514
547
|
(_this$dataProvider5 = this.dataProvider) === null || _this$dataProvider5 === void 0 ? void 0 : _this$dataProvider5.removeFromCache([resourceId]);
|
|
515
548
|
this._providerFactoryManager.deleteFactory(resourceId);
|
|
516
549
|
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Schedules a delayed retry for a block that returned EntityNotFound.
|
|
553
|
+
* The block may be in the process of being created by a collaborator —
|
|
554
|
+
* the NCS transaction propagates the bodiedSyncBlock ADF node before
|
|
555
|
+
* the Block Service createBlock call completes.
|
|
556
|
+
*/
|
|
557
|
+
scheduleEntityNotFoundRetry(resourceId) {
|
|
558
|
+
var _this$entityNotFoundR2;
|
|
559
|
+
const currentRetries = (_this$entityNotFoundR2 = this.entityNotFoundRetryCount.get(resourceId)) !== null && _this$entityNotFoundR2 !== void 0 ? _this$entityNotFoundR2 : 0;
|
|
560
|
+
if (currentRetries >= ENTITY_NOT_FOUND_MAX_RETRIES) {
|
|
561
|
+
// Max retries exceeded — keep count at max so future calls immediately exit
|
|
562
|
+
// (don't delete — that would reset the counter and allow unbounded retry waves)
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// If a timer is already pending, don't schedule another one — let the
|
|
567
|
+
// existing timer fire. This prevents rapid EntityNotFound responses from
|
|
568
|
+
// exhausting the retry budget through cancellations without any actual
|
|
569
|
+
// fetch completing.
|
|
570
|
+
if (this.entityNotFoundRetryTimers.has(resourceId)) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
const delay = ENTITY_NOT_FOUND_INITIAL_DELAY_MS * Math.pow(2, currentRetries);
|
|
574
|
+
const timer = setTimeout(() => {
|
|
575
|
+
var _cached$error;
|
|
576
|
+
this.entityNotFoundRetryTimers.delete(resourceId);
|
|
577
|
+
|
|
578
|
+
// If no active subscriptions remain for this block, clean up and skip
|
|
579
|
+
const subscriptions = this._subscriptionManager.getSubscriptions().get(resourceId);
|
|
580
|
+
if (!subscriptions || Object.keys(subscriptions).length === 0) {
|
|
581
|
+
this.entityNotFoundRetryCount.delete(resourceId);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// Increment count only when the timer fires, not when scheduled
|
|
586
|
+
this.entityNotFoundRetryCount.set(resourceId, currentRetries + 1);
|
|
587
|
+
|
|
588
|
+
// Clear the error from cache so fetchSyncBlocksData doesn't skip it
|
|
589
|
+
const cached = this.getFromCache(resourceId);
|
|
590
|
+
if ((cached === null || cached === void 0 ? void 0 : (_cached$error = cached.error) === null || _cached$error === void 0 ? void 0 : _cached$error.type) === SyncBlockError.EntityNotFound) {
|
|
591
|
+
this.deleteFromCache(resourceId);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Trigger a re-fetch via the batch fetcher
|
|
595
|
+
this.debouncedBatchedFetchSyncBlocks(resourceId);
|
|
596
|
+
}, delay);
|
|
597
|
+
this.entityNotFoundRetryTimers.set(resourceId, timer);
|
|
598
|
+
}
|
|
517
599
|
debouncedBatchedFetchSyncBlocks(resourceId) {
|
|
518
600
|
this._batchFetcher.queueFetch(resourceId);
|
|
519
601
|
}
|
|
@@ -691,6 +773,11 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
691
773
|
clearTimeout(this.queuedFlushTimeout);
|
|
692
774
|
this.queuedFlushTimeout = undefined;
|
|
693
775
|
}
|
|
776
|
+
|
|
777
|
+
// Cancel any pending EntityNotFound retry timers
|
|
778
|
+
this.entityNotFoundRetryTimers.forEach(timer => clearTimeout(timer));
|
|
779
|
+
this.entityNotFoundRetryTimers.clear();
|
|
780
|
+
this.entityNotFoundRetryCount.clear();
|
|
694
781
|
this._subscriptionManager.destroy();
|
|
695
782
|
this._providerFactoryManager.destroy();
|
|
696
783
|
this._batchFetcher.destroy();
|
|
@@ -22,6 +22,8 @@ import { syncBlockInMemorySessionCache } from './syncBlockInMemorySessionCache';
|
|
|
22
22
|
import { SyncBlockProviderFactoryManager } from './syncBlockProviderFactoryManager';
|
|
23
23
|
import { SyncBlockSubscriptionManager } from './syncBlockSubscriptionManager';
|
|
24
24
|
var CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
25
|
+
var ENTITY_NOT_FOUND_MAX_RETRIES = 3;
|
|
26
|
+
var ENTITY_NOT_FOUND_INITIAL_DELAY_MS = 2000;
|
|
25
27
|
|
|
26
28
|
// A store manager responsible for the lifecycle and state management of reference sync blocks in an editor instance.
|
|
27
29
|
// Designed to manage local in-memory state and synchronize with an external data provider.
|
|
@@ -29,8 +31,6 @@ var CACHE_KEY_PREFIX = 'sync-block-data-';
|
|
|
29
31
|
// Handles fetching source URL and title for sync blocks.
|
|
30
32
|
// Can be used in both editor and renderer contexts.
|
|
31
33
|
export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
32
|
-
// Track the setTimeout handle for queued flush so we can cancel it on destroy
|
|
33
|
-
|
|
34
34
|
function ReferenceSyncBlockStoreManager(dataProvider, viewMode) {
|
|
35
35
|
var _this = this,
|
|
36
36
|
_this$dataProvider;
|
|
@@ -45,6 +45,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
45
45
|
_defineProperty(this, "isFlushInProgress", false);
|
|
46
46
|
// Track if another flush is needed after the current one completes
|
|
47
47
|
_defineProperty(this, "flushNeededAfterCurrent", false);
|
|
48
|
+
// Track retry attempts for EntityNotFound errors (block may be in the process of being created)
|
|
49
|
+
_defineProperty(this, "entityNotFoundRetryCount", new Map());
|
|
50
|
+
_defineProperty(this, "entityNotFoundRetryTimers", new Map());
|
|
48
51
|
this.dataProvider = dataProvider;
|
|
49
52
|
this.viewMode = viewMode;
|
|
50
53
|
this.syncBlockFetchDataRequests = new Map();
|
|
@@ -204,6 +207,8 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
204
207
|
var syncBlockNode = createSyncBlockNode('', resourceId);
|
|
205
208
|
var providerData = (_this$dataProvider2 = this.dataProvider) === null || _this$dataProvider2 === void 0 || (_this$dataProvider2 = _this$dataProvider2.getNodeDataFromCache(syncBlockNode)) === null || _this$dataProvider2 === void 0 ? void 0 : _this$dataProvider2.data;
|
|
206
209
|
if (providerData) {
|
|
210
|
+
// Initial provider cache data can come from SSR/prefetch and bypass updateCache(),
|
|
211
|
+
// so strip annotations here before references render existing synced block payloads.
|
|
207
212
|
return this.stripAnnotationMarksFromReferenceData(providerData);
|
|
208
213
|
}
|
|
209
214
|
return this.getFromSessionCache(resourceId);
|
|
@@ -241,6 +246,8 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
241
246
|
if (!raw) {
|
|
242
247
|
return undefined;
|
|
243
248
|
}
|
|
249
|
+
// Session cache entries written before this sanitizer existed may still include
|
|
250
|
+
// source annotation marks, so keep this read-time safety net for legacy data.
|
|
244
251
|
return this.stripAnnotationMarksFromReferenceData(JSON.parse(raw));
|
|
245
252
|
} catch (error) {
|
|
246
253
|
logException(error, {
|
|
@@ -570,11 +577,37 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
570
577
|
// Remove from newly added set even if not unpublished (to clean up)
|
|
571
578
|
_this5.newlyAddedSyncBlocks.delete(syncBlockInstance.resourceId);
|
|
572
579
|
}
|
|
580
|
+
|
|
581
|
+
// Clear retry tracking on successful fetch — block has been created
|
|
582
|
+
if (!syncBlockInstance.error && _this5.entityNotFoundRetryCount.has(syncBlockInstance.resourceId)) {
|
|
583
|
+
var timer = _this5.entityNotFoundRetryTimers.get(syncBlockInstance.resourceId);
|
|
584
|
+
if (timer) {
|
|
585
|
+
clearTimeout(timer);
|
|
586
|
+
_this5.entityNotFoundRetryTimers.delete(syncBlockInstance.resourceId);
|
|
587
|
+
}
|
|
588
|
+
_this5.entityNotFoundRetryCount.delete(syncBlockInstance.resourceId);
|
|
589
|
+
}
|
|
573
590
|
if (syncBlockInstance.error) {
|
|
574
|
-
var _this5$
|
|
575
|
-
|
|
591
|
+
var _this5$entityNotFound;
|
|
592
|
+
// Skip error analytics when EntityNotFound will be retried, to avoid
|
|
593
|
+
// inflating error-rate metrics with expected transient failures
|
|
594
|
+
var isRetryingEntityNotFound = syncBlockInstance.error.type === SyncBlockError.EntityNotFound && ((_this5$entityNotFound = _this5.entityNotFoundRetryCount.get(syncBlockInstance.resourceId)) !== null && _this5$entityNotFound !== void 0 ? _this5$entityNotFound : 0) < ENTITY_NOT_FOUND_MAX_RETRIES && fg('platform_synced_block_patch_13');
|
|
595
|
+
if (!isRetryingEntityNotFound) {
|
|
596
|
+
var _this5$fireAnalyticsE2, _syncBlockInstance$da, _syncBlockInstance$da2;
|
|
597
|
+
(_this5$fireAnalyticsE2 = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE2 === void 0 || _this5$fireAnalyticsE2.call(_this5, fetchErrorPayload(syncBlockInstance.error.reason || syncBlockInstance.error.type, syncBlockInstance.resourceId, (_syncBlockInstance$da = (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product) !== null && _syncBlockInstance$da !== void 0 ? _syncBlockInstance$da : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId)));
|
|
598
|
+
}
|
|
576
599
|
if (syncBlockInstance.error.type === SyncBlockError.NotFound || syncBlockInstance.error.type === SyncBlockError.Forbidden) {
|
|
577
600
|
hasExpectedError = true;
|
|
601
|
+
} else if (syncBlockInstance.error.type === SyncBlockError.EntityNotFound) {
|
|
602
|
+
// Schedule a retry for EntityNotFound — the source block may be in
|
|
603
|
+
// the process of being created by a collaborator (race condition
|
|
604
|
+
// between NCS propagation and Block Service createBlock call).
|
|
605
|
+
if (fg('platform_synced_block_patch_13')) {
|
|
606
|
+
_this5.scheduleEntityNotFoundRetry(syncBlockInstance.resourceId);
|
|
607
|
+
}
|
|
608
|
+
if (!isRetryingEntityNotFound) {
|
|
609
|
+
hasUnexpectedError = true;
|
|
610
|
+
}
|
|
578
611
|
} else if (syncBlockInstance.error) {
|
|
579
612
|
hasUnexpectedError = true;
|
|
580
613
|
}
|
|
@@ -638,6 +671,58 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
638
671
|
(_this$dataProvider5 = this.dataProvider) === null || _this$dataProvider5 === void 0 || _this$dataProvider5.removeFromCache([resourceId]);
|
|
639
672
|
this._providerFactoryManager.deleteFactory(resourceId);
|
|
640
673
|
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Schedules a delayed retry for a block that returned EntityNotFound.
|
|
677
|
+
* The block may be in the process of being created by a collaborator —
|
|
678
|
+
* the NCS transaction propagates the bodiedSyncBlock ADF node before
|
|
679
|
+
* the Block Service createBlock call completes.
|
|
680
|
+
*/
|
|
681
|
+
}, {
|
|
682
|
+
key: "scheduleEntityNotFoundRetry",
|
|
683
|
+
value: function scheduleEntityNotFoundRetry(resourceId) {
|
|
684
|
+
var _this$entityNotFoundR,
|
|
685
|
+
_this6 = this;
|
|
686
|
+
var currentRetries = (_this$entityNotFoundR = this.entityNotFoundRetryCount.get(resourceId)) !== null && _this$entityNotFoundR !== void 0 ? _this$entityNotFoundR : 0;
|
|
687
|
+
if (currentRetries >= ENTITY_NOT_FOUND_MAX_RETRIES) {
|
|
688
|
+
// Max retries exceeded — keep count at max so future calls immediately exit
|
|
689
|
+
// (don't delete — that would reset the counter and allow unbounded retry waves)
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// If a timer is already pending, don't schedule another one — let the
|
|
694
|
+
// existing timer fire. This prevents rapid EntityNotFound responses from
|
|
695
|
+
// exhausting the retry budget through cancellations without any actual
|
|
696
|
+
// fetch completing.
|
|
697
|
+
if (this.entityNotFoundRetryTimers.has(resourceId)) {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
var delay = ENTITY_NOT_FOUND_INITIAL_DELAY_MS * Math.pow(2, currentRetries);
|
|
701
|
+
var timer = setTimeout(function () {
|
|
702
|
+
var _cached$error;
|
|
703
|
+
_this6.entityNotFoundRetryTimers.delete(resourceId);
|
|
704
|
+
|
|
705
|
+
// If no active subscriptions remain for this block, clean up and skip
|
|
706
|
+
var subscriptions = _this6._subscriptionManager.getSubscriptions().get(resourceId);
|
|
707
|
+
if (!subscriptions || Object.keys(subscriptions).length === 0) {
|
|
708
|
+
_this6.entityNotFoundRetryCount.delete(resourceId);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Increment count only when the timer fires, not when scheduled
|
|
713
|
+
_this6.entityNotFoundRetryCount.set(resourceId, currentRetries + 1);
|
|
714
|
+
|
|
715
|
+
// Clear the error from cache so fetchSyncBlocksData doesn't skip it
|
|
716
|
+
var cached = _this6.getFromCache(resourceId);
|
|
717
|
+
if ((cached === null || cached === void 0 || (_cached$error = cached.error) === null || _cached$error === void 0 ? void 0 : _cached$error.type) === SyncBlockError.EntityNotFound) {
|
|
718
|
+
_this6.deleteFromCache(resourceId);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Trigger a re-fetch via the batch fetcher
|
|
722
|
+
_this6.debouncedBatchedFetchSyncBlocks(resourceId);
|
|
723
|
+
}, delay);
|
|
724
|
+
this.entityNotFoundRetryTimers.set(resourceId, timer);
|
|
725
|
+
}
|
|
641
726
|
}, {
|
|
642
727
|
key: "debouncedBatchedFetchSyncBlocks",
|
|
643
728
|
value: function debouncedBatchedFetchSyncBlocks(resourceId) {
|
|
@@ -646,12 +731,12 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
646
731
|
}, {
|
|
647
732
|
key: "setSSRDataInSessionCache",
|
|
648
733
|
value: function setSSRDataInSessionCache(resourceIds) {
|
|
649
|
-
var
|
|
734
|
+
var _this7 = this;
|
|
650
735
|
if (!resourceIds || resourceIds.length === 0) {
|
|
651
736
|
return;
|
|
652
737
|
}
|
|
653
738
|
resourceIds.forEach(function (resourceId) {
|
|
654
|
-
|
|
739
|
+
_this7.updateSessionCache(resourceId);
|
|
655
740
|
});
|
|
656
741
|
}
|
|
657
742
|
}, {
|
|
@@ -724,7 +809,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
724
809
|
key: "flush",
|
|
725
810
|
value: (function () {
|
|
726
811
|
var _flush = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
727
|
-
var
|
|
812
|
+
var _this8 = this;
|
|
728
813
|
var success, syncedBlocksToFlush, _this$saveExperience, blocks, _iterator, _step, _loop, updateResult, _this$saveExperience2, _this$fireAnalyticsEv6, _this$saveExperience3, _this$fireAnalyticsEv7, _this$saveExperience4;
|
|
729
814
|
return _regeneratorRuntime.wrap(function _callee3$(_context4) {
|
|
730
815
|
while (1) switch (_context4.prev = _context4.next) {
|
|
@@ -866,8 +951,8 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
866
951
|
// Use setTimeout to avoid deep recursion and run queued flush asynchronously
|
|
867
952
|
// Note: flush() handles all exceptions internally and never rejects
|
|
868
953
|
this.queuedFlushTimeout = setTimeout(function () {
|
|
869
|
-
|
|
870
|
-
void
|
|
954
|
+
_this8.queuedFlushTimeout = undefined;
|
|
955
|
+
void _this8.flush();
|
|
871
956
|
}, 0);
|
|
872
957
|
}
|
|
873
958
|
return _context4.finish(49);
|
|
@@ -893,6 +978,13 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
893
978
|
clearTimeout(this.queuedFlushTimeout);
|
|
894
979
|
this.queuedFlushTimeout = undefined;
|
|
895
980
|
}
|
|
981
|
+
|
|
982
|
+
// Cancel any pending EntityNotFound retry timers
|
|
983
|
+
this.entityNotFoundRetryTimers.forEach(function (timer) {
|
|
984
|
+
return clearTimeout(timer);
|
|
985
|
+
});
|
|
986
|
+
this.entityNotFoundRetryTimers.clear();
|
|
987
|
+
this.entityNotFoundRetryCount.clear();
|
|
896
988
|
this._subscriptionManager.destroy();
|
|
897
989
|
this._providerFactoryManager.destroy();
|
|
898
990
|
this._batchFetcher.destroy();
|
|
@@ -18,6 +18,8 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
18
18
|
private isFlushInProgress;
|
|
19
19
|
private flushNeededAfterCurrent;
|
|
20
20
|
private queuedFlushTimeout?;
|
|
21
|
+
private entityNotFoundRetryCount;
|
|
22
|
+
private entityNotFoundRetryTimers;
|
|
21
23
|
fetchExperience: Experience | undefined;
|
|
22
24
|
private fetchSourceInfoExperience;
|
|
23
25
|
private saveExperience;
|
|
@@ -88,6 +90,13 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
88
90
|
private updateCache;
|
|
89
91
|
getFromCache(resourceId: ResourceId): SyncBlockInstance | undefined;
|
|
90
92
|
private deleteFromCache;
|
|
93
|
+
/**
|
|
94
|
+
* Schedules a delayed retry for a block that returned EntityNotFound.
|
|
95
|
+
* The block may be in the process of being created by a collaborator —
|
|
96
|
+
* the NCS transaction propagates the bodiedSyncBlock ADF node before
|
|
97
|
+
* the Block Service createBlock call completes.
|
|
98
|
+
*/
|
|
99
|
+
private scheduleEntityNotFoundRetry;
|
|
91
100
|
private debouncedBatchedFetchSyncBlocks;
|
|
92
101
|
private setSSRDataInSessionCache;
|
|
93
102
|
subscribeToSyncBlock(resourceId: string, localId: string, callback: SubscriptionCallback): () => void;
|
|
@@ -18,6 +18,8 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
18
18
|
private isFlushInProgress;
|
|
19
19
|
private flushNeededAfterCurrent;
|
|
20
20
|
private queuedFlushTimeout?;
|
|
21
|
+
private entityNotFoundRetryCount;
|
|
22
|
+
private entityNotFoundRetryTimers;
|
|
21
23
|
fetchExperience: Experience | undefined;
|
|
22
24
|
private fetchSourceInfoExperience;
|
|
23
25
|
private saveExperience;
|
|
@@ -88,6 +90,13 @@ export declare class ReferenceSyncBlockStoreManager {
|
|
|
88
90
|
private updateCache;
|
|
89
91
|
getFromCache(resourceId: ResourceId): SyncBlockInstance | undefined;
|
|
90
92
|
private deleteFromCache;
|
|
93
|
+
/**
|
|
94
|
+
* Schedules a delayed retry for a block that returned EntityNotFound.
|
|
95
|
+
* The block may be in the process of being created by a collaborator —
|
|
96
|
+
* the NCS transaction propagates the bodiedSyncBlock ADF node before
|
|
97
|
+
* the Block Service createBlock call completes.
|
|
98
|
+
*/
|
|
99
|
+
private scheduleEntityNotFoundRetry;
|
|
91
100
|
private debouncedBatchedFetchSyncBlocks;
|
|
92
101
|
private setSSRDataInSessionCache;
|
|
93
102
|
subscribeToSyncBlock(resourceId: string, localId: string, callback: SubscriptionCallback): () => void;
|
package/package.json
CHANGED
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
],
|
|
25
25
|
"atlaskit:src": "src/index.ts",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@atlaskit/adf-utils": "^19.
|
|
27
|
+
"@atlaskit/adf-utils": "^19.31.0",
|
|
28
28
|
"@atlaskit/editor-json-transformer": "^8.32.0",
|
|
29
29
|
"@atlaskit/editor-prosemirror": "^7.3.0",
|
|
30
30
|
"@atlaskit/node-data-provider": "^11.1.0",
|
|
31
31
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
32
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
32
|
+
"@atlaskit/tmp-editor-statsig": "^83.0.0",
|
|
33
33
|
"@babel/runtime": "^7.0.0",
|
|
34
34
|
"@compiled/react": "^0.20.0",
|
|
35
35
|
"graphql-ws": "^5.14.2",
|
|
@@ -38,11 +38,12 @@
|
|
|
38
38
|
"uuid": "^3.1.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@atlaskit/editor-common": "^114.
|
|
41
|
+
"@atlaskit/editor-common": "^114.46.0",
|
|
42
42
|
"react": "^18.2.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@testing-library/react": "^16.3.0",
|
|
46
|
+
"react": "^18.2.0",
|
|
46
47
|
"react-dom": "^18.2.0"
|
|
47
48
|
},
|
|
48
49
|
"techstack": {
|
|
@@ -81,7 +82,7 @@
|
|
|
81
82
|
}
|
|
82
83
|
},
|
|
83
84
|
"name": "@atlaskit/editor-synced-block-provider",
|
|
84
|
-
"version": "6.6.
|
|
85
|
+
"version": "6.6.9",
|
|
85
86
|
"description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
|
|
86
87
|
"author": "Atlassian Pty Ltd",
|
|
87
88
|
"license": "Apache-2.0",
|
|
@@ -91,6 +92,9 @@
|
|
|
91
92
|
"platform-feature-flags": {
|
|
92
93
|
"platform_synced_block_patch_12": {
|
|
93
94
|
"type": "boolean"
|
|
95
|
+
},
|
|
96
|
+
"platform_synced_block_patch_13": {
|
|
97
|
+
"type": "boolean"
|
|
94
98
|
}
|
|
95
99
|
}
|
|
96
100
|
}
|