@atlaskit/editor-synced-block-provider 3.12.0 → 3.13.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 (56) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/cjs/clients/block-service/blockSubscription.js +124 -0
  3. package/dist/cjs/clients/jira/sourceInfo.js +152 -0
  4. package/dist/cjs/providers/block-service/blockServiceAPI.js +43 -6
  5. package/dist/cjs/providers/syncBlockProvider.js +40 -8
  6. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +393 -204
  7. package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +95 -124
  8. package/dist/cjs/store-manager/syncBlockStoreManager.js +2 -2
  9. package/dist/cjs/utils/errorHandling.js +79 -19
  10. package/dist/cjs/utils/experienceTracking.js +119 -0
  11. package/dist/cjs/utils/resolveSyncBlockInstance.js +1 -1
  12. package/dist/es2019/clients/block-service/blockSubscription.js +125 -0
  13. package/dist/es2019/clients/jira/sourceInfo.js +87 -0
  14. package/dist/es2019/providers/block-service/blockServiceAPI.js +40 -5
  15. package/dist/es2019/providers/syncBlockProvider.js +26 -2
  16. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +286 -139
  17. package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +80 -89
  18. package/dist/es2019/store-manager/syncBlockStoreManager.js +2 -2
  19. package/dist/es2019/utils/errorHandling.js +61 -10
  20. package/dist/es2019/utils/experienceTracking.js +113 -0
  21. package/dist/es2019/utils/resolveSyncBlockInstance.js +1 -1
  22. package/dist/esm/clients/block-service/blockSubscription.js +118 -0
  23. package/dist/esm/clients/jira/sourceInfo.js +147 -0
  24. package/dist/esm/providers/block-service/blockServiceAPI.js +43 -6
  25. package/dist/esm/providers/syncBlockProvider.js +38 -6
  26. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +394 -205
  27. package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +96 -125
  28. package/dist/esm/store-manager/syncBlockStoreManager.js +2 -2
  29. package/dist/esm/utils/errorHandling.js +77 -18
  30. package/dist/esm/utils/experienceTracking.js +113 -0
  31. package/dist/esm/utils/resolveSyncBlockInstance.js +1 -1
  32. package/dist/types/clients/block-service/blockService.d.ts +2 -2
  33. package/dist/types/clients/block-service/blockSubscription.d.ts +38 -0
  34. package/dist/types/clients/jira/sourceInfo.d.ts +2 -0
  35. package/dist/types/common/types.d.ts +4 -2
  36. package/dist/types/index.d.ts +2 -2
  37. package/dist/types/providers/block-service/blockServiceAPI.d.ts +8 -0
  38. package/dist/types/providers/syncBlockProvider.d.ts +9 -1
  39. package/dist/types/providers/types.d.ts +22 -6
  40. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +59 -1
  41. package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +1 -5
  42. package/dist/types/utils/errorHandling.d.ts +14 -9
  43. package/dist/types/utils/experienceTracking.d.ts +51 -0
  44. package/dist/types-ts4.5/clients/block-service/blockService.d.ts +2 -2
  45. package/dist/types-ts4.5/clients/block-service/blockSubscription.d.ts +38 -0
  46. package/dist/types-ts4.5/clients/jira/sourceInfo.d.ts +2 -0
  47. package/dist/types-ts4.5/common/types.d.ts +4 -2
  48. package/dist/types-ts4.5/index.d.ts +2 -2
  49. package/dist/types-ts4.5/providers/block-service/blockServiceAPI.d.ts +8 -0
  50. package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +9 -1
  51. package/dist/types-ts4.5/providers/types.d.ts +22 -6
  52. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +59 -1
  53. package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +1 -5
  54. package/dist/types-ts4.5/utils/errorHandling.d.ts +14 -9
  55. package/dist/types-ts4.5/utils/experienceTracking.d.ts +51 -0
  56. package/package.json +2 -1
@@ -16,6 +16,7 @@ var _providerFactory = require("@atlaskit/editor-common/provider-factory");
16
16
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
17
  var _types = require("../common/types");
18
18
  var _errorHandling = require("../utils/errorHandling");
19
+ var _experienceTracking = require("../utils/experienceTracking");
19
20
  var _resolveSyncBlockInstance = require("../utils/resolveSyncBlockInstance");
20
21
  var _resourceId = require("../utils/resourceId");
21
22
  var _utils = require("../utils/utils");
@@ -30,18 +31,17 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
30
31
  // Handles fetching source URL and title for sync blocks.
31
32
  // Can be used in both editor and renderer contexts.
32
33
  var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
33
- // Track pending cache deletions to handle block moves (unmount/remount)
34
- // When a block is moved, the old component unmounts before the new one mounts,
35
- // causing the cache to be deleted prematurely. We delay deletion to allow
36
- // the new component to subscribe and cancel the pending deletion.
34
+ // Listeners for subscription changes (used by React components to know when to update)
37
35
 
38
36
  function ReferenceSyncBlockStoreManager(dataProvider) {
39
37
  (0, _classCallCheck2.default)(this, ReferenceSyncBlockStoreManager);
40
38
  // Keeps track of addition and deletion of reference synced blocks on the document
41
39
  // This starts as true to always flush the cache when document is saved for the first time
42
- // to cater the case when a editor seesion is closed without document being updated right after reference block is deleted
40
+ // to cater the case when a editor session is closed without document being updated right after reference block is deleted
43
41
  (0, _defineProperty2.default)(this, "isCacheDirty", true);
44
42
  (0, _defineProperty2.default)(this, "isRefreshingSubscriptions", false);
43
+ // Flag to indicate if real-time subscriptions are enabled
44
+ (0, _defineProperty2.default)(this, "useRealTimeSubscriptions", false);
45
45
  this.syncBlockCache = new Map();
46
46
  this.subscriptions = new Map();
47
47
  this.titleSubscriptions = new Map();
@@ -51,22 +51,112 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
51
51
  this.syncBlockSourceInfoRequests = new Map();
52
52
  this.providerFactories = new Map();
53
53
  this.pendingCacheDeletions = new Map();
54
+ this.graphqlSubscriptions = new Map();
55
+ this.subscriptionChangeListeners = new Set();
54
56
  }
57
+
58
+ /**
59
+ * Enables or disables real-time GraphQL subscriptions for block updates.
60
+ * When enabled, the store manager will subscribe to real-time updates
61
+ * instead of relying on polling.
62
+ * @param enabled - Whether to enable real-time subscriptions
63
+ */
55
64
  return (0, _createClass2.default)(ReferenceSyncBlockStoreManager, [{
56
- key: "setFireAnalyticsEvent",
57
- value: function setFireAnalyticsEvent(fireAnalyticsEvent) {
58
- this.fireAnalyticsEvent = fireAnalyticsEvent;
65
+ key: "setRealTimeSubscriptionsEnabled",
66
+ value: function setRealTimeSubscriptionsEnabled(enabled) {
67
+ if (this.useRealTimeSubscriptions === enabled) {
68
+ return;
69
+ }
70
+ this.useRealTimeSubscriptions = enabled;
71
+ if (enabled) {
72
+ // Set up subscriptions for all currently subscribed blocks
73
+ this.setupGraphQLSubscriptionsForAllBlocks();
74
+ } else {
75
+ // Clean up all GraphQL subscriptions
76
+ this.cleanupAllGraphQLSubscriptions();
77
+ }
59
78
  }
79
+
80
+ /**
81
+ * Checks if real-time subscriptions are currently enabled.
82
+ */
60
83
  }, {
61
- key: "setExperiences",
62
- value: function setExperiences(fetchExperience, fetchSourceInfoExperience, saveExperience) {
63
- // don't reset experiences after they have already been set
64
- if (!this.fetchExperience || !this.fetchSourceInfoExperience || !this.saveExperience) {
65
- this.fetchExperience = fetchExperience;
66
- this.fetchSourceInfoExperience = fetchSourceInfoExperience;
67
- this.saveExperience = saveExperience;
84
+ key: "isRealTimeSubscriptionsEnabled",
85
+ value: function isRealTimeSubscriptionsEnabled() {
86
+ return this.useRealTimeSubscriptions;
87
+ }
88
+
89
+ /**
90
+ * Returns all resource IDs that are currently subscribed to.
91
+ * Used by React components to render subscription components.
92
+ */
93
+ }, {
94
+ key: "getSubscribedResourceIds",
95
+ value: function getSubscribedResourceIds() {
96
+ return Array.from(this.subscriptions.keys());
97
+ }
98
+
99
+ /**
100
+ * Registers a listener that will be called when subscriptions change.
101
+ * @param listener - Callback function to invoke when subscriptions change
102
+ * @returns Unsubscribe function to remove the listener
103
+ */
104
+ }, {
105
+ key: "onSubscriptionsChanged",
106
+ value: function onSubscriptionsChanged(listener) {
107
+ var _this = this;
108
+ this.subscriptionChangeListeners.add(listener);
109
+ return function () {
110
+ _this.subscriptionChangeListeners.delete(listener);
111
+ };
112
+ }
113
+
114
+ /**
115
+ * Notifies all subscription change listeners.
116
+ */
117
+ }, {
118
+ key: "notifySubscriptionChangeListeners",
119
+ value: function notifySubscriptionChangeListeners() {
120
+ var _this2 = this;
121
+ this.subscriptionChangeListeners.forEach(function (listener) {
122
+ try {
123
+ listener();
124
+ } catch (error) {
125
+ var _this2$fireAnalyticsE;
126
+ (0, _monitoring.logException)(error, {
127
+ location: 'editor-synced-block-provider/referenceSyncBlockStoreManager/notifySubscriptionChangeListeners'
128
+ });
129
+ (_this2$fireAnalyticsE = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE === void 0 || _this2$fireAnalyticsE.call(_this2, (0, _errorHandling.fetchErrorPayload)(error.message));
130
+ }
131
+ });
132
+ }
133
+
134
+ /**
135
+ * Handles incoming data from a GraphQL subscription.
136
+ * Called by React subscription components when they receive updates.
137
+ * @param syncBlockInstance - The updated sync block instance
138
+ */
139
+ }, {
140
+ key: "handleSubscriptionUpdate",
141
+ value: function handleSubscriptionUpdate(syncBlockInstance) {
142
+ if (!syncBlockInstance.resourceId) {
143
+ return;
144
+ }
145
+ var existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
146
+ var resolvedSyncBlockInstance = existingSyncBlock ? (0, _resolveSyncBlockInstance.resolveSyncBlockInstance)(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
147
+ this.updateCache(resolvedSyncBlockInstance);
148
+ if (!syncBlockInstance.error) {
149
+ this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
68
150
  }
69
151
  }
152
+ }, {
153
+ key: "setFireAnalyticsEvent",
154
+ value: function setFireAnalyticsEvent(fireAnalyticsEvent) {
155
+ this.fireAnalyticsEvent = fireAnalyticsEvent;
156
+ this.fetchExperience = (0, _experienceTracking.getFetchExperience)(fireAnalyticsEvent);
157
+ this.fetchSourceInfoExperience = (0, _experienceTracking.getFetchSourceInfoExperience)(fireAnalyticsEvent);
158
+ this.saveExperience = (0, _experienceTracking.getSaveReferenceExperience)(fireAnalyticsEvent);
159
+ }
70
160
  }, {
71
161
  key: "generateResourceIdForReference",
72
162
  value: function generateResourceIdForReference(sourceId) {
@@ -90,26 +180,33 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
90
180
 
91
181
  /**
92
182
  * Refreshes the subscriptions for all sync blocks.
183
+ * This is a fallback polling mechanism when real-time subscriptions are not enabled.
93
184
  * @returns {Promise<void>}
94
185
  */
95
186
  }, {
96
187
  key: "refreshSubscriptions",
97
188
  value: (function () {
98
189
  var _refreshSubscriptions = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
99
- var syncBlocks, _iterator, _step, _loop, _this$fetchExperience, _this$fireAnalyticsEv;
190
+ var syncBlocks, _iterator, _step, _loop, _this$fireAnalyticsEv;
100
191
  return _regenerator.default.wrap(function _callee$(_context2) {
101
192
  while (1) switch (_context2.prev = _context2.next) {
102
193
  case 0:
103
- if (!this.isRefreshingSubscriptions) {
194
+ if (!this.useRealTimeSubscriptions) {
104
195
  _context2.next = 2;
105
196
  break;
106
197
  }
107
198
  return _context2.abrupt("return");
108
199
  case 2:
200
+ if (!this.isRefreshingSubscriptions) {
201
+ _context2.next = 4;
202
+ break;
203
+ }
204
+ return _context2.abrupt("return");
205
+ case 4:
109
206
  this.isRefreshingSubscriptions = true;
110
207
  syncBlocks = [];
111
208
  _iterator = _createForOfIteratorHelper(this.subscriptions.entries());
112
- _context2.prev = 5;
209
+ _context2.prev = 7;
113
210
  _loop = /*#__PURE__*/_regenerator.default.mark(function _loop() {
114
211
  var _step$value, resourceId, callbacks;
115
212
  return _regenerator.default.wrap(function _loop$(_context) {
@@ -126,72 +223,165 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
126
223
  }, _loop);
127
224
  });
128
225
  _iterator.s();
129
- case 8:
226
+ case 10:
130
227
  if ((_step = _iterator.n()).done) {
131
- _context2.next = 12;
228
+ _context2.next = 14;
132
229
  break;
133
230
  }
134
- return _context2.delegateYield(_loop(), "t0", 10);
135
- case 10:
136
- _context2.next = 8;
137
- break;
231
+ return _context2.delegateYield(_loop(), "t0", 12);
138
232
  case 12:
139
- _context2.next = 17;
233
+ _context2.next = 10;
140
234
  break;
141
235
  case 14:
142
- _context2.prev = 14;
143
- _context2.t1 = _context2["catch"](5);
236
+ _context2.next = 19;
237
+ break;
238
+ case 16:
239
+ _context2.prev = 16;
240
+ _context2.t1 = _context2["catch"](7);
144
241
  _iterator.e(_context2.t1);
145
- case 17:
146
- _context2.prev = 17;
242
+ case 19:
243
+ _context2.prev = 19;
147
244
  _iterator.f();
148
- return _context2.finish(17);
149
- case 20:
150
- _context2.prev = 20;
151
- _context2.next = 23;
245
+ return _context2.finish(19);
246
+ case 22:
247
+ _context2.prev = 22;
248
+ _context2.next = 25;
152
249
  return this.fetchSyncBlocksData(syncBlocks);
153
- case 23:
154
- _context2.next = 29;
155
- break;
156
250
  case 25:
157
- _context2.prev = 25;
158
- _context2.t2 = _context2["catch"](20);
251
+ _context2.next = 31;
252
+ break;
253
+ case 27:
254
+ _context2.prev = 27;
255
+ _context2.t2 = _context2["catch"](22);
159
256
  (0, _monitoring.logException)(_context2.t2, {
160
257
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
161
258
  });
162
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
163
- (_this$fetchExperience = this.fetchExperience) === null || _this$fetchExperience === void 0 || _this$fetchExperience.failure({
164
- reason: _context2.t2.message
165
- });
166
- } else {
167
- (_this$fireAnalyticsEv = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv === void 0 || _this$fireAnalyticsEv.call(this, (0, _errorHandling.fetchErrorPayload)(_context2.t2.message));
168
- }
169
- case 29:
170
- _context2.prev = 29;
259
+ (_this$fireAnalyticsEv = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv === void 0 || _this$fireAnalyticsEv.call(this, (0, _errorHandling.fetchErrorPayload)(_context2.t2.message));
260
+ case 31:
261
+ _context2.prev = 31;
171
262
  this.isRefreshingSubscriptions = false;
172
- return _context2.finish(29);
173
- case 32:
263
+ return _context2.finish(31);
264
+ case 34:
174
265
  case "end":
175
266
  return _context2.stop();
176
267
  }
177
- }, _callee, this, [[5, 14, 17, 20], [20, 25, 29, 32]]);
268
+ }, _callee, this, [[7, 16, 19, 22], [22, 27, 31, 34]]);
178
269
  }));
179
270
  function refreshSubscriptions() {
180
271
  return _refreshSubscriptions.apply(this, arguments);
181
272
  }
182
273
  return refreshSubscriptions;
183
- }())
274
+ }()
275
+ /**
276
+ * Sets up a GraphQL subscription for a specific block.
277
+ * @param resourceId - The resource ID of the block to subscribe to
278
+ */
279
+ )
280
+ }, {
281
+ key: "setupGraphQLSubscription",
282
+ value: function setupGraphQLSubscription(resourceId) {
283
+ var _this$dataProvider2,
284
+ _this3 = this;
285
+ // Don't set up duplicate subscriptions
286
+ if (this.graphqlSubscriptions.has(resourceId)) {
287
+ return;
288
+ }
289
+ if (!((_this$dataProvider2 = this.dataProvider) !== null && _this$dataProvider2 !== void 0 && _this$dataProvider2.subscribeToBlockUpdates)) {
290
+ return;
291
+ }
292
+ var unsubscribe = this.dataProvider.subscribeToBlockUpdates(resourceId, function (syncBlockInstance) {
293
+ // Handle the subscription update
294
+ _this3.handleGraphQLSubscriptionUpdate(syncBlockInstance);
295
+ }, function (error) {
296
+ var _this3$fireAnalyticsE;
297
+ (0, _monitoring.logException)(error, {
298
+ location: 'editor-synced-block-provider/referenceSyncBlockStoreManager/graphql-subscription'
299
+ });
300
+ (_this3$fireAnalyticsE = _this3.fireAnalyticsEvent) === null || _this3$fireAnalyticsE === void 0 || _this3$fireAnalyticsE.call(_this3, (0, _errorHandling.fetchErrorPayload)(error.message));
301
+ });
302
+ if (unsubscribe) {
303
+ this.graphqlSubscriptions.set(resourceId, unsubscribe);
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Handles updates received from GraphQL subscriptions.
309
+ * @param syncBlockInstance - The updated sync block instance
310
+ */
311
+ }, {
312
+ key: "handleGraphQLSubscriptionUpdate",
313
+ value: function handleGraphQLSubscriptionUpdate(syncBlockInstance) {
314
+ if (!syncBlockInstance.resourceId) {
315
+ return;
316
+ }
317
+ var existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
318
+ var resolvedSyncBlockInstance = existingSyncBlock ? (0, _resolveSyncBlockInstance.resolveSyncBlockInstance)(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
319
+ this.updateCache(resolvedSyncBlockInstance);
320
+ if (!syncBlockInstance.error) {
321
+ this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Cleans up the GraphQL subscription for a specific block.
327
+ * @param resourceId - The resource ID of the block to unsubscribe from
328
+ */
329
+ }, {
330
+ key: "cleanupGraphQLSubscription",
331
+ value: function cleanupGraphQLSubscription(resourceId) {
332
+ var unsubscribe = this.graphqlSubscriptions.get(resourceId);
333
+ if (unsubscribe) {
334
+ unsubscribe();
335
+ this.graphqlSubscriptions.delete(resourceId);
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Sets up GraphQL subscriptions for all currently subscribed blocks.
341
+ */
342
+ }, {
343
+ key: "setupGraphQLSubscriptionsForAllBlocks",
344
+ value: function setupGraphQLSubscriptionsForAllBlocks() {
345
+ var _iterator2 = _createForOfIteratorHelper(this.subscriptions.keys()),
346
+ _step2;
347
+ try {
348
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
349
+ var resourceId = _step2.value;
350
+ this.setupGraphQLSubscription(resourceId);
351
+ }
352
+ } catch (err) {
353
+ _iterator2.e(err);
354
+ } finally {
355
+ _iterator2.f();
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Cleans up all GraphQL subscriptions.
361
+ */
362
+ }, {
363
+ key: "cleanupAllGraphQLSubscriptions",
364
+ value: function cleanupAllGraphQLSubscriptions() {
365
+ var _iterator3 = _createForOfIteratorHelper(this.graphqlSubscriptions.values()),
366
+ _step3;
367
+ try {
368
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
369
+ var unsubscribe = _step3.value;
370
+ unsubscribe();
371
+ }
372
+ } catch (err) {
373
+ _iterator3.e(err);
374
+ } finally {
375
+ _iterator3.f();
376
+ }
377
+ this.graphqlSubscriptions.clear();
378
+ }
184
379
  }, {
185
380
  key: "fetchSyncBlockSourceInfo",
186
381
  value: function fetchSyncBlockSourceInfo(resourceId) {
187
- var _this = this;
382
+ var _this4 = this;
188
383
  try {
189
384
  if (!resourceId || !this.dataProvider) {
190
- // make sure experience has been started before throwing error
191
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
192
- var _this$fetchSourceInfo;
193
- (_this$fetchSourceInfo = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo === void 0 || _this$fetchSourceInfo.start({});
194
- }
195
385
  throw new Error('Data provider or resourceId not set');
196
386
  }
197
387
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
@@ -204,10 +394,6 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
204
394
  }
205
395
  var existingSyncBlock = this.getFromCache(resourceId);
206
396
  if (!existingSyncBlock) {
207
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
208
- var _this$fetchSourceInfo2;
209
- (_this$fetchSourceInfo2 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo2 === void 0 || _this$fetchSourceInfo2.start({});
210
- }
211
397
  throw new Error('No existing sync block to fetch source info for');
212
398
  }
213
399
  var _ref = existingSyncBlock.data || {},
@@ -216,7 +402,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
216
402
  blockInstanceId = _ref.blockInstanceId,
217
403
  sourceURL = _ref.sourceURL,
218
404
  sourceTitle = _ref.sourceTitle,
219
- onSamePage = _ref.onSamePage,
405
+ onSameDocument = _ref.onSameDocument,
220
406
  sourceSubType = _ref.sourceSubType;
221
407
  // skip if source URL and title are already present
222
408
  if (sourceURL && sourceTitle) {
@@ -226,73 +412,65 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
226
412
  url: sourceURL,
227
413
  subType: sourceSubType,
228
414
  sourceAri: sourceAri || '',
229
- onSamePage: onSamePage,
415
+ onSameDocument: onSameDocument,
230
416
  productType: product
231
417
  });
232
418
  } else {
233
419
  return Promise.resolve(undefined);
234
420
  }
235
421
  }
236
-
237
- // only start experience if there is data to fetch
238
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
239
- var _this$fetchSourceInfo3;
240
- (_this$fetchSourceInfo3 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo3 === void 0 || _this$fetchSourceInfo3.start({});
241
- }
242
422
  if (!sourceAri || !product || !blockInstanceId) {
243
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
244
- var _this$fetchSourceInfo4;
245
- (_this$fetchSourceInfo4 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo4 === void 0 || _this$fetchSourceInfo4.failure({
246
- reason: 'SourceAri, product or blockInstanceId missing'
247
- });
248
- } else {
249
- var _this$fireAnalyticsEv2;
250
- (_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 || _this$fireAnalyticsEv2.call(this, (0, _errorHandling.getSourceInfoErrorPayload)('SourceAri, product or blockInstanceId missing'));
251
- }
423
+ var _this$fireAnalyticsEv2;
424
+ (_this$fireAnalyticsEv2 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv2 === void 0 || _this$fireAnalyticsEv2.call(this, (0, _errorHandling.getSourceInfoErrorPayload)('SourceAri, product or blockInstanceId missing', resourceId));
252
425
  return Promise.resolve(undefined);
253
426
  }
427
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
428
+ var _this$fetchSourceInfo;
429
+ (_this$fetchSourceInfo = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo === void 0 || _this$fetchSourceInfo.start({});
430
+ }
254
431
  var sourceInfoPromise = this.dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, sourceAri, product, this.fireAnalyticsEvent).then(function (sourceInfo) {
255
432
  if (!sourceInfo) {
256
433
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
257
- var _this$fetchSourceInfo5;
258
- (_this$fetchSourceInfo5 = _this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo5 === void 0 || _this$fetchSourceInfo5.failure({
434
+ var _this4$fetchSourceInf, _this4$fireAnalyticsE;
435
+ (_this4$fetchSourceInf = _this4.fetchSourceInfoExperience) === null || _this4$fetchSourceInf === void 0 || _this4$fetchSourceInf.failure({
259
436
  reason: 'No source info returned'
260
437
  });
438
+ (_this4$fireAnalyticsE = _this4.fireAnalyticsEvent) === null || _this4$fireAnalyticsE === void 0 || _this4$fireAnalyticsE.call(_this4, (0, _errorHandling.getSourceInfoErrorPayload)('No source info returned', resourceId));
261
439
  }
262
440
  return undefined;
263
441
  }
264
- _this.updateCacheWithSourceInfo(resourceId, sourceInfo);
442
+ _this4.updateCacheWithSourceInfo(resourceId, sourceInfo);
265
443
  if (sourceInfo.title) {
266
- _this.updateSourceTitleSubscriptions(resourceId, sourceInfo.title);
444
+ _this4.updateSourceTitleSubscriptions(resourceId, sourceInfo.title);
267
445
  }
268
446
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
269
447
  if (sourceInfo.title && sourceInfo.url) {
270
- var _this$fetchSourceInfo6;
271
- (_this$fetchSourceInfo6 = _this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo6 === void 0 || _this$fetchSourceInfo6.success();
448
+ var _this4$fetchSourceInf2;
449
+ (_this4$fetchSourceInf2 = _this4.fetchSourceInfoExperience) === null || _this4$fetchSourceInf2 === void 0 || _this4$fetchSourceInf2.success();
272
450
  } else {
273
- var _this$fetchSourceInfo7;
274
- (_this$fetchSourceInfo7 = _this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo7 === void 0 || _this$fetchSourceInfo7.failure({
451
+ var _this4$fetchSourceInf3, _this4$fireAnalyticsE2;
452
+ (_this4$fetchSourceInf3 = _this4.fetchSourceInfoExperience) === null || _this4$fetchSourceInf3 === void 0 || _this4$fetchSourceInf3.failure({
275
453
  reason: 'Missing title or url'
276
454
  });
455
+ (_this4$fireAnalyticsE2 = _this4.fireAnalyticsEvent) === null || _this4$fireAnalyticsE2 === void 0 || _this4$fireAnalyticsE2.call(_this4, (0, _errorHandling.getSourceInfoErrorPayload)('Missing title or url', resourceId));
277
456
  }
278
457
  return sourceInfo;
279
458
  }
280
459
  }).catch(function (error) {
460
+ var _this4$fireAnalyticsE3;
281
461
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
282
- var _this$fetchSourceInfo8;
283
- (_this$fetchSourceInfo8 = _this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo8 === void 0 || _this$fetchSourceInfo8.failure({
462
+ var _this4$fetchSourceInf4;
463
+ (_this4$fetchSourceInf4 = _this4.fetchSourceInfoExperience) === null || _this4$fetchSourceInf4 === void 0 || _this4$fetchSourceInf4.failure({
284
464
  reason: error.message
285
465
  });
286
- } else {
287
- var _this$fireAnalyticsEv3;
288
- (_this$fireAnalyticsEv3 = _this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(_this, (0, _errorHandling.getSourceInfoErrorPayload)(error.message));
289
466
  }
467
+ (_this4$fireAnalyticsE3 = _this4.fireAnalyticsEvent) === null || _this4$fireAnalyticsE3 === void 0 || _this4$fireAnalyticsE3.call(_this4, (0, _errorHandling.getSourceInfoErrorPayload)(error.message, resourceId));
290
468
  return undefined;
291
469
  }).finally(function () {
292
470
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
293
- _this.syncBlockSourceInfoRequests.delete(resourceId);
471
+ _this4.syncBlockSourceInfoRequests.delete(resourceId);
294
472
  } else {
295
- _this.syncBlockSourceInfoRequestsOld.delete(resourceId);
473
+ _this4.syncBlockSourceInfoRequestsOld.delete(resourceId);
296
474
  }
297
475
  });
298
476
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
@@ -302,18 +480,11 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
302
480
  this.syncBlockSourceInfoRequestsOld.set(resourceId, true);
303
481
  }
304
482
  } catch (error) {
483
+ var _this$fireAnalyticsEv3;
305
484
  (0, _monitoring.logException)(error, {
306
485
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
307
486
  });
308
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
309
- var _this$fetchSourceInfo9;
310
- (_this$fetchSourceInfo9 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo9 === void 0 || _this$fetchSourceInfo9.failure({
311
- reason: error.message
312
- });
313
- } else {
314
- var _this$fireAnalyticsEv4;
315
- (_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 || _this$fireAnalyticsEv4.call(this, (0, _errorHandling.getSourceInfoErrorPayload)(error.message));
316
- }
487
+ (_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(this, (0, _errorHandling.getSourceInfoErrorPayload)(error.message, resourceId));
317
488
  }
318
489
  return Promise.resolve(undefined);
319
490
  }
@@ -327,8 +498,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
327
498
  key: "fetchSyncBlocksData",
328
499
  value: (function () {
329
500
  var _fetchSyncBlocksData = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(syncBlockNodes) {
330
- var _this2 = this;
331
- var nodesToFetch, _this$fetchExperience2, data, resolvedData, successfulFetched, failedFetch, _this$fetchExperience3, _this$fetchExperience4;
501
+ var _this5 = this;
502
+ var nodesToFetch, _this$fetchExperience, data, resolvedData, hasUnexpectedError, hasExpectedError, _this$fetchExperience2, _this$fetchExperience3, _this$fetchExperience4;
332
503
  return _regenerator.default.wrap(function _callee2$(_context3) {
333
504
  while (1) switch (_context3.prev = _context3.next) {
334
505
  case 0:
@@ -341,10 +512,10 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
341
512
  // Don't fetch for not_found error since the source is already deleted
342
513
  nodesToFetch = [];
343
514
  syncBlockNodes.forEach(function (node) {
344
- if (_this2.syncBlockFetchDataRequests.get(node.attrs.resourceId)) {
515
+ if (_this5.syncBlockFetchDataRequests.get(node.attrs.resourceId)) {
345
516
  return;
346
517
  }
347
- var existingSyncBlock = _this2.getFromCache(node.attrs.resourceId);
518
+ var existingSyncBlock = _this5.getFromCache(node.attrs.resourceId);
348
519
  if ((existingSyncBlock === null || existingSyncBlock === void 0 ? void 0 : existingSyncBlock.error) === _types.SyncBlockError.NotFound) {
349
520
  return;
350
521
  }
@@ -356,77 +527,65 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
356
527
  }
357
528
  return _context3.abrupt("return");
358
529
  case 6:
359
- // only start fetch experience if there is data to fetch
360
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
361
- (_this$fetchExperience2 = this.fetchExperience) === null || _this$fetchExperience2 === void 0 || _this$fetchExperience2.start({});
362
- }
363
530
  if (this.dataProvider) {
364
- _context3.next = 9;
531
+ _context3.next = 8;
365
532
  break;
366
533
  }
367
534
  throw new Error('Data provider not set');
368
- case 9:
535
+ case 8:
369
536
  nodesToFetch.forEach(function (node) {
370
- _this2.syncBlockFetchDataRequests.set(node.attrs.resourceId, true);
537
+ _this5.syncBlockFetchDataRequests.set(node.attrs.resourceId, true);
371
538
  });
539
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
540
+ (_this$fetchExperience = this.fetchExperience) === null || _this$fetchExperience === void 0 || _this$fetchExperience.start({});
541
+ }
372
542
  _context3.next = 12;
373
543
  return this.dataProvider.fetchNodesData(nodesToFetch).finally(function () {
374
544
  nodesToFetch.forEach(function (node) {
375
- _this2.syncBlockFetchDataRequests.delete(node.attrs.resourceId);
545
+ _this5.syncBlockFetchDataRequests.delete(node.attrs.resourceId);
376
546
  });
377
547
  });
378
548
  case 12:
379
549
  data = _context3.sent;
380
550
  resolvedData = [];
381
- successfulFetched = [];
382
- failedFetch = [];
551
+ hasUnexpectedError = false;
552
+ hasExpectedError = false;
383
553
  data.forEach(function (syncBlockInstance) {
384
554
  if (!syncBlockInstance.resourceId) {
385
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
386
- failedFetch.push({
387
- reason: syncBlockInstance.error || 'Returned sync block instance does not have resource id'
388
- });
389
- } else {
390
- var _this2$fireAnalyticsE;
391
- (_this2$fireAnalyticsE = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE === void 0 || _this2$fireAnalyticsE.call(_this2, (0, _errorHandling.fetchErrorPayload)(syncBlockInstance.error || 'Returned sync block instance does not have resource id'));
392
- }
555
+ var _this5$fireAnalyticsE;
556
+ (_this5$fireAnalyticsE = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE === void 0 || _this5$fireAnalyticsE.call(_this5, (0, _errorHandling.fetchErrorPayload)(syncBlockInstance.error || 'Returned sync block instance does not have resource id'));
393
557
  return;
394
558
  }
395
- var existingSyncBlock = _this2.getFromCache(syncBlockInstance.resourceId);
559
+ var existingSyncBlock = _this5.getFromCache(syncBlockInstance.resourceId);
396
560
  var resolvedSyncBlockInstance = existingSyncBlock ? (0, _resolveSyncBlockInstance.resolveSyncBlockInstance)(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
397
- _this2.updateCache(resolvedSyncBlockInstance);
561
+ _this5.updateCache(resolvedSyncBlockInstance);
398
562
  resolvedData.push(resolvedSyncBlockInstance);
399
563
  if (syncBlockInstance.error) {
400
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
401
- failedFetch.push({
402
- reason: syncBlockInstance.error,
403
- resourceId: syncBlockInstance.resourceId
404
- });
405
- } else {
406
- var _this2$fireAnalyticsE2;
407
- (_this2$fireAnalyticsE2 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE2 === void 0 || _this2$fireAnalyticsE2.call(_this2, (0, _errorHandling.fetchErrorPayload)(syncBlockInstance.error));
564
+ var _this5$fireAnalyticsE2;
565
+ (_this5$fireAnalyticsE2 = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE2 === void 0 || _this5$fireAnalyticsE2.call(_this5, (0, _errorHandling.fetchErrorPayload)(syncBlockInstance.error, syncBlockInstance.resourceId));
566
+ if (syncBlockInstance.error === _types.SyncBlockError.NotFound || syncBlockInstance.error === _types.SyncBlockError.Forbidden) {
567
+ hasExpectedError = true;
568
+ } else if (syncBlockInstance.error) {
569
+ hasUnexpectedError = true;
408
570
  }
409
571
  return;
572
+ } else if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
573
+ var _this5$fireAnalyticsE3, _syncBlockInstance$da, _syncBlockInstance$da2;
574
+ (_this5$fireAnalyticsE3 = _this5.fireAnalyticsEvent) === null || _this5$fireAnalyticsE3 === void 0 || _this5$fireAnalyticsE3.call(_this5, (0, _errorHandling.fetchSuccessPayload)(syncBlockInstance.resourceId, (_syncBlockInstance$da = syncBlockInstance.data) === null || _syncBlockInstance$da === void 0 ? void 0 : _syncBlockInstance$da.blockInstanceId, (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product));
410
575
  }
411
- successfulFetched.push(syncBlockInstance.resourceId);
412
- _this2.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
576
+ _this5.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
413
577
  });
414
578
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
415
- if (data.every(function (syncBlockInstance) {
416
- return syncBlockInstance.resourceId && !syncBlockInstance.error;
417
- })) {
418
- (_this$fetchExperience3 = this.fetchExperience) === null || _this$fetchExperience3 === void 0 || _this$fetchExperience3.success({
419
- metadata: {
420
- successfulFetched: successfulFetched
421
- }
579
+ if (hasUnexpectedError) {
580
+ (_this$fetchExperience2 = this.fetchExperience) === null || _this$fetchExperience2 === void 0 || _this$fetchExperience2.failure({
581
+ reason: 'Unexpected error during fetch'
422
582
  });
423
- } else {
424
- (_this$fetchExperience4 = this.fetchExperience) === null || _this$fetchExperience4 === void 0 || _this$fetchExperience4.failure({
425
- metadata: {
426
- successfulFetched: successfulFetched,
427
- failedFetch: failedFetch
428
- }
583
+ } else if (hasExpectedError) {
584
+ (_this$fetchExperience3 = this.fetchExperience) === null || _this$fetchExperience3 === void 0 || _this$fetchExperience3.abort({
585
+ reason: 'Expected error: NotFound or PermissionDenied'
429
586
  });
587
+ } else {
588
+ (_this$fetchExperience4 = this.fetchExperience) === null || _this$fetchExperience4 === void 0 || _this$fetchExperience4.success();
430
589
  }
431
590
  }
432
591
  case 18:
@@ -449,7 +608,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
449
608
  existingSyncBlock.data = _objectSpread(_objectSpread({}, existingSyncBlock.data), {}, {
450
609
  sourceURL: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.url,
451
610
  sourceTitle: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.title,
452
- onSamePage: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.onSamePage,
611
+ onSameDocument: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.onSameDocument,
453
612
  sourceSubType: sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.subType
454
613
  });
455
614
  this.updateCache(existingSyncBlock);
@@ -493,8 +652,8 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
493
652
  }, {
494
653
  key: "subscribeToSyncBlock",
495
654
  value: function subscribeToSyncBlock(resourceId, localId, callback) {
496
- var _this$dataProvider2,
497
- _this3 = this;
655
+ var _this$dataProvider3,
656
+ _this6 = this;
498
657
  // Cancel any pending cache deletion for this resourceId.
499
658
  // This handles the case where a block is moved - the old component unmounts
500
659
  // (scheduling deletion) but the new component mounts and subscribes before
@@ -507,41 +666,52 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
507
666
 
508
667
  // add to subscriptions map
509
668
  var resourceSubscriptions = this.subscriptions.get(resourceId) || {};
669
+ var isNewResourceSubscription = Object.keys(resourceSubscriptions).length === 0;
510
670
  this.subscriptions.set(resourceId, _objectSpread(_objectSpread({}, resourceSubscriptions), {}, (0, _defineProperty2.default)({}, localId, callback)));
511
671
 
512
672
  // New subscription means new reference synced block is added to the document
513
673
  this.isCacheDirty = true;
674
+
675
+ // Notify listeners if this is a new resource subscription
676
+ if (isNewResourceSubscription) {
677
+ this.notifySubscriptionChangeListeners();
678
+ }
514
679
  var syncBlockNode = (0, _utils.createSyncBlockNode)(localId, resourceId);
515
680
 
516
681
  // call the callback immediately if we have cached data
517
682
  // prefer cache from store manager first, should update data provider to use the same cache
518
- var cachedData = this.getFromCache(resourceId) || ((_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);
683
+ var cachedData = this.getFromCache(resourceId) || ((_this$dataProvider3 = this.dataProvider) === null || _this$dataProvider3 === void 0 || (_this$dataProvider3 = _this$dataProvider3.getNodeDataFromCache(syncBlockNode)) === null || _this$dataProvider3 === void 0 ? void 0 : _this$dataProvider3.data);
519
684
  if (cachedData) {
520
685
  callback(cachedData);
521
686
  } else {
522
687
  this.fetchSyncBlocksData([syncBlockNode]).catch(function (error) {
688
+ var _this6$fireAnalyticsE;
523
689
  (0, _monitoring.logException)(error, {
524
690
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
525
691
  });
526
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
527
- var _this3$fetchExperienc;
528
- (_this3$fetchExperienc = _this3.fetchExperience) === null || _this3$fetchExperienc === void 0 || _this3$fetchExperienc.failure({
529
- reason: error.message
530
- });
531
- } else {
532
- var _this3$fireAnalyticsE;
533
- (_this3$fireAnalyticsE = _this3.fireAnalyticsEvent) === null || _this3$fireAnalyticsE === void 0 || _this3$fireAnalyticsE.call(_this3, (0, _errorHandling.fetchErrorPayload)(error.message));
534
- }
692
+ (_this6$fireAnalyticsE = _this6.fireAnalyticsEvent) === null || _this6$fireAnalyticsE === void 0 || _this6$fireAnalyticsE.call(_this6, (0, _errorHandling.fetchErrorPayload)(error.message, resourceId));
535
693
  });
536
694
  }
695
+
696
+ // Set up GraphQL subscription if real-time subscriptions are enabled
697
+ if (this.useRealTimeSubscriptions) {
698
+ this.setupGraphQLSubscription(resourceId);
699
+ }
537
700
  return function () {
538
- var resourceSubscriptions = _this3.subscriptions.get(resourceId);
701
+ var resourceSubscriptions = _this6.subscriptions.get(resourceId);
539
702
  if (resourceSubscriptions) {
540
703
  // Unsubscription means a reference synced block is removed from the document
541
- _this3.isCacheDirty = true;
704
+ _this6.isCacheDirty = true;
542
705
  delete resourceSubscriptions[localId];
543
706
  if (Object.keys(resourceSubscriptions).length === 0) {
544
- _this3.subscriptions.delete(resourceId);
707
+ _this6.subscriptions.delete(resourceId);
708
+
709
+ // Clean up GraphQL subscription when no more local subscribers
710
+ _this6.cleanupGraphQLSubscription(resourceId);
711
+
712
+ // Notify listeners that subscription was removed
713
+ _this6.notifySubscriptionChangeListeners();
714
+
545
715
  // Delay cache deletion to handle block moves (unmount/remount).
546
716
  // When a block is moved, the old component unmounts before the new one mounts.
547
717
  // By delaying deletion, we give the new component time to subscribe and
@@ -549,14 +719,14 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
549
719
  // TODO: EDITOR-4152 - Rework this logic
550
720
  var deletionTimeout = setTimeout(function () {
551
721
  // Only delete if still no subscribers (wasn't re-subscribed)
552
- if (!_this3.subscriptions.has(resourceId)) {
553
- _this3.deleteFromCache(resourceId);
722
+ if (!_this6.subscriptions.has(resourceId)) {
723
+ _this6.deleteFromCache(resourceId);
554
724
  }
555
- _this3.pendingCacheDeletions.delete(resourceId);
725
+ _this6.pendingCacheDeletions.delete(resourceId);
556
726
  }, 1000);
557
- _this3.pendingCacheDeletions.set(resourceId, deletionTimeout);
727
+ _this6.pendingCacheDeletions.set(resourceId, deletionTimeout);
558
728
  } else {
559
- _this3.subscriptions.set(resourceId, resourceSubscriptions);
729
+ _this6.subscriptions.set(resourceId, resourceSubscriptions);
560
730
  }
561
731
  }
562
732
  };
@@ -565,7 +735,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
565
735
  key: "subscribeToSourceTitle",
566
736
  value: function subscribeToSourceTitle(node, callback) {
567
737
  var _cachedData$data,
568
- _this4 = this;
738
+ _this7 = this;
569
739
  // check node is a sync block, as we only support sync block subscriptions
570
740
  if (node.type.name !== 'syncBlock') {
571
741
  return function () {};
@@ -585,13 +755,13 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
585
755
  var resourceSubscriptions = this.titleSubscriptions.get(resourceId) || {};
586
756
  this.titleSubscriptions.set(resourceId, _objectSpread(_objectSpread({}, resourceSubscriptions), {}, (0, _defineProperty2.default)({}, localId, callback)));
587
757
  return function () {
588
- var resourceSubscriptions = _this4.titleSubscriptions.get(resourceId);
758
+ var resourceSubscriptions = _this7.titleSubscriptions.get(resourceId);
589
759
  if (resourceSubscriptions) {
590
760
  delete resourceSubscriptions[localId];
591
761
  if (Object.keys(resourceSubscriptions).length === 0) {
592
- _this4.titleSubscriptions.delete(resourceId);
762
+ _this7.titleSubscriptions.delete(resourceId);
593
763
  } else {
594
- _this4.titleSubscriptions.set(resourceId, resourceSubscriptions);
764
+ _this7.titleSubscriptions.set(resourceId, resourceSubscriptions);
595
765
  }
596
766
  }
597
767
  };
@@ -612,11 +782,11 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
612
782
  }
613
783
  return this.subscribeToSyncBlock(resourceId, localId, callback);
614
784
  } catch (error) {
615
- var _this$fireAnalyticsEv5;
785
+ var _this$fireAnalyticsEv4;
616
786
  (0, _monitoring.logException)(error, {
617
787
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
618
788
  });
619
- (_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 || _this$fireAnalyticsEv5.call(this, (0, _errorHandling.fetchErrorPayload)(error.message));
789
+ (_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 || _this$fireAnalyticsEv4.call(this, (0, _errorHandling.fetchErrorPayload)(error.message));
620
790
  return function () {};
621
791
  }
622
792
  }
@@ -640,12 +810,12 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
640
810
  key: "getProviderFactory",
641
811
  value: function getProviderFactory(resourceId) {
642
812
  if (!this.dataProvider) {
643
- var _this$fireAnalyticsEv6;
813
+ var _this$fireAnalyticsEv5;
644
814
  var error = new Error('Data provider not set');
645
815
  (0, _monitoring.logException)(error, {
646
816
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
647
817
  });
648
- (_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 || _this$fireAnalyticsEv6.call(this, (0, _errorHandling.fetchErrorPayload)(error.message));
818
+ (_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 || _this$fireAnalyticsEv5.call(this, (0, _errorHandling.fetchErrorPayload)(error.message));
649
819
  return undefined;
650
820
  }
651
821
  var _this$dataProvider$ge = this.dataProvider.getSyncedBlockRendererProviderOptions(),
@@ -674,11 +844,11 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
674
844
  try {
675
845
  this.retrieveDynamicProviders(resourceId, providerFactory, providerCreator);
676
846
  } catch (error) {
677
- var _this$fireAnalyticsEv7;
847
+ var _this$fireAnalyticsEv6;
678
848
  (0, _monitoring.logException)(error, {
679
849
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
680
850
  });
681
- (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 || _this$fireAnalyticsEv7.call(this, (0, _errorHandling.fetchErrorPayload)(error.message));
851
+ (_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 || _this$fireAnalyticsEv6.call(this, (0, _errorHandling.fetchErrorPayload)(error.message, resourceId));
682
852
  }
683
853
  }
684
854
  return providerFactory;
@@ -734,9 +904,12 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
734
904
  return;
735
905
  }
736
906
  var syncBlock = this.getFromCache(resourceId);
737
- if (!syncBlock || !((_syncBlock$data2 = syncBlock.data) !== null && _syncBlock$data2 !== void 0 && _syncBlock$data2.sourceAri) || !((_syncBlock$data3 = syncBlock.data) !== null && _syncBlock$data3 !== void 0 && _syncBlock$data3.product)) {
738
- var _this$fireAnalyticsEv8;
739
- (_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 || _this$fireAnalyticsEv8.call(this, (0, _errorHandling.fetchErrorPayload)('Sync block or source ari or product not found'));
907
+ if (!syncBlock) {
908
+ return;
909
+ }
910
+ if (!((_syncBlock$data2 = syncBlock.data) !== null && _syncBlock$data2 !== void 0 && _syncBlock$data2.sourceAri) || !((_syncBlock$data3 = syncBlock.data) !== null && _syncBlock$data3 !== void 0 && _syncBlock$data3.product)) {
911
+ var _this$fireAnalyticsEv7;
912
+ (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 || _this$fireAnalyticsEv7.call(this, (0, _errorHandling.fetchErrorPayload)('Sync block source ari or product not found'));
740
913
  return;
741
914
  }
742
915
  var parentInfo = this.dataProvider.retrieveSyncBlockParentInfo((_syncBlock$data4 = syncBlock.data) === null || _syncBlock$data4 === void 0 ? void 0 : _syncBlock$data4.sourceAri, (_syncBlock$data5 = syncBlock.data) === null || _syncBlock$data5 === void 0 ? void 0 : _syncBlock$data5.product);
@@ -786,7 +959,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
786
959
  key: "flush",
787
960
  value: (function () {
788
961
  var _flush = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
789
- var success, blocks, _this$saveExperience, updateResult, _this$saveExperience2, _this$fireAnalyticsEv9, _this$saveExperience3, _this$fireAnalyticsEv0, _this$saveExperience4;
962
+ var success, blocks, _this$saveExperience, updateResult, _this$fireAnalyticsEv8, _this$saveExperience2, _this$fireAnalyticsEv9, _this$saveExperience3, _this$saveExperience4;
790
963
  return _regenerator.default.wrap(function _callee3$(_context4) {
791
964
  while (1) switch (_context4.prev = _context4.next) {
792
965
  case 0:
@@ -810,16 +983,17 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
810
983
  });
811
984
  });
812
985
  });
986
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
987
+ _context4.next = 10;
988
+ break;
989
+ }
813
990
  if (!(blocks.length === 0)) {
814
- _context4.next = 9;
991
+ _context4.next = 10;
815
992
  break;
816
993
  }
817
994
  this.isCacheDirty = false;
818
995
  return _context4.abrupt("return", true);
819
- case 9:
820
- if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
821
- (_this$saveExperience = this.saveExperience) === null || _this$saveExperience === void 0 || _this$saveExperience.start();
822
- }
996
+ case 10:
823
997
  if (this.dataProvider) {
824
998
  _context4.next = 12;
825
999
  break;
@@ -832,9 +1006,12 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
832
1006
  // is still making changes, the new changes might not be saved if they all happen
833
1007
  // exactly at a time when the updateReferenceData is being executed asynchronously.
834
1008
  this.isCacheDirty = false;
835
- _context4.next = 15;
1009
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
1010
+ (_this$saveExperience = this.saveExperience) === null || _this$saveExperience === void 0 || _this$saveExperience.start();
1011
+ }
1012
+ _context4.next = 16;
836
1013
  return this.dataProvider.updateReferenceData(blocks);
837
- case 15:
1014
+ case 16:
838
1015
  updateResult = _context4.sent;
839
1016
  if (!updateResult.success) {
840
1017
  success = false;
@@ -842,14 +1019,13 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
842
1019
  (_this$saveExperience2 = this.saveExperience) === null || _this$saveExperience2 === void 0 || _this$saveExperience2.failure({
843
1020
  reason: updateResult.error || 'Failed to update reference synced blocks on the document'
844
1021
  });
845
- } else {
846
- (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, (0, _errorHandling.updateReferenceErrorPayload)(updateResult.error || 'Failed to update reference synced blocks on the document'));
847
1022
  }
1023
+ (_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 || _this$fireAnalyticsEv8.call(this, (0, _errorHandling.updateReferenceErrorPayload)(updateResult.error || 'Failed to update reference synced blocks on the document'));
848
1024
  }
849
- _context4.next = 24;
1025
+ _context4.next = 26;
850
1026
  break;
851
- case 19:
852
- _context4.prev = 19;
1027
+ case 20:
1028
+ _context4.prev = 20;
853
1029
  _context4.t0 = _context4["catch"](3);
854
1030
  success = false;
855
1031
  (0, _monitoring.logException)(_context4.t0, {
@@ -859,25 +1035,24 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
859
1035
  (_this$saveExperience3 = this.saveExperience) === null || _this$saveExperience3 === void 0 || _this$saveExperience3.failure({
860
1036
  reason: _context4.t0.message
861
1037
  });
862
- } else {
863
- (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, (0, _errorHandling.updateReferenceErrorPayload)(_context4.t0.message));
864
1038
  }
865
- case 24:
866
- _context4.prev = 24;
1039
+ (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, (0, _errorHandling.updateReferenceErrorPayload)(_context4.t0.message));
1040
+ case 26:
1041
+ _context4.prev = 26;
867
1042
  if (!success) {
868
1043
  // set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
869
1044
  this.isCacheDirty = true;
870
1045
  } else if ((0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
871
1046
  (_this$saveExperience4 = this.saveExperience) === null || _this$saveExperience4 === void 0 || _this$saveExperience4.success();
872
1047
  }
873
- return _context4.finish(24);
874
- case 27:
1048
+ return _context4.finish(26);
1049
+ case 29:
875
1050
  return _context4.abrupt("return", success);
876
- case 28:
1051
+ case 30:
877
1052
  case "end":
878
1053
  return _context4.stop();
879
1054
  }
880
- }, _callee3, this, [[3, 19, 24, 27]]);
1055
+ }, _callee3, this, [[3, 20, 26, 29]]);
881
1056
  }));
882
1057
  function flush() {
883
1058
  return _flush.apply(this, arguments);
@@ -887,6 +1062,9 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
887
1062
  }, {
888
1063
  key: "destroy",
889
1064
  value: function destroy() {
1065
+ var _this$saveExperience5, _this$fetchExperience5, _this$fetchSourceInfo2;
1066
+ // Clean up all GraphQL subscriptions first
1067
+ this.cleanupAllGraphQLSubscriptions();
890
1068
  this.dataProvider = undefined;
891
1069
  this.syncBlockCache.clear();
892
1070
  this.subscriptions.clear();
@@ -896,10 +1074,21 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
896
1074
  this.syncBlockSourceInfoRequests.clear();
897
1075
  this.providerFactories.clear();
898
1076
  this.isRefreshingSubscriptions = false;
1077
+ this.useRealTimeSubscriptions = false;
1078
+ this.subscriptionChangeListeners.clear();
899
1079
  this.providerFactories.forEach(function (providerFactory) {
900
1080
  providerFactory.destroy();
901
1081
  });
902
1082
  this.providerFactories.clear();
1083
+ (_this$saveExperience5 = this.saveExperience) === null || _this$saveExperience5 === void 0 || _this$saveExperience5.abort({
1084
+ reason: 'editor-destroyed'
1085
+ });
1086
+ (_this$fetchExperience5 = this.fetchExperience) === null || _this$fetchExperience5 === void 0 || _this$fetchExperience5.abort({
1087
+ reason: 'editor-destroyed'
1088
+ });
1089
+ (_this$fetchSourceInfo2 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo2 === void 0 || _this$fetchSourceInfo2.abort({
1090
+ reason: 'editor-destroyed'
1091
+ });
903
1092
  this.fireAnalyticsEvent = undefined;
904
1093
  }
905
1094
  }]);