@atlaskit/editor-synced-block-provider 3.14.1 → 3.14.3

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 (49) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/clients/block-service/blockService.js +21 -16
  3. package/dist/cjs/hooks/useFetchSyncBlockData.js +3 -1
  4. package/dist/cjs/providers/block-service/blockServiceAPI.js +75 -36
  5. package/dist/cjs/providers/syncBlockProvider.js +10 -6
  6. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +65 -26
  7. package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +68 -28
  8. package/dist/cjs/store-manager/syncBlockStoreManager.js +54 -23
  9. package/dist/cjs/utils/experienceTracking.js +18 -1
  10. package/dist/cjs/utils/resolveSyncBlockInstance.js +2 -1
  11. package/dist/es2019/clients/block-service/blockService.js +10 -3
  12. package/dist/es2019/hooks/useFetchSyncBlockData.js +3 -1
  13. package/dist/es2019/providers/block-service/blockServiceAPI.js +62 -23
  14. package/dist/es2019/providers/syncBlockProvider.js +8 -4
  15. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +71 -36
  16. package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +55 -17
  17. package/dist/es2019/store-manager/syncBlockStoreManager.js +37 -3
  18. package/dist/es2019/utils/experienceTracking.js +17 -0
  19. package/dist/es2019/utils/resolveSyncBlockInstance.js +2 -1
  20. package/dist/esm/clients/block-service/blockService.js +21 -16
  21. package/dist/esm/hooks/useFetchSyncBlockData.js +3 -1
  22. package/dist/esm/providers/block-service/blockServiceAPI.js +75 -36
  23. package/dist/esm/providers/syncBlockProvider.js +10 -6
  24. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +65 -26
  25. package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +70 -30
  26. package/dist/esm/store-manager/syncBlockStoreManager.js +54 -23
  27. package/dist/esm/utils/experienceTracking.js +17 -0
  28. package/dist/esm/utils/resolveSyncBlockInstance.js +2 -1
  29. package/dist/types/clients/block-service/blockService.d.ts +7 -4
  30. package/dist/types/common/types.d.ts +4 -0
  31. package/dist/types/index.d.ts +1 -1
  32. package/dist/types/providers/block-service/blockServiceAPI.d.ts +6 -3
  33. package/dist/types/providers/syncBlockProvider.d.ts +2 -2
  34. package/dist/types/providers/types.d.ts +8 -4
  35. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +9 -0
  36. package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +5 -3
  37. package/dist/types/store-manager/syncBlockStoreManager.d.ts +2 -0
  38. package/dist/types/utils/experienceTracking.d.ts +8 -0
  39. package/dist/types-ts4.5/clients/block-service/blockService.d.ts +7 -4
  40. package/dist/types-ts4.5/common/types.d.ts +4 -0
  41. package/dist/types-ts4.5/index.d.ts +1 -1
  42. package/dist/types-ts4.5/providers/block-service/blockServiceAPI.d.ts +6 -3
  43. package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +2 -2
  44. package/dist/types-ts4.5/providers/types.d.ts +8 -4
  45. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +9 -0
  46. package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +5 -3
  47. package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +2 -0
  48. package/dist/types-ts4.5/utils/experienceTracking.d.ts +8 -0
  49. package/package.json +2 -2
@@ -17,6 +17,10 @@ import { createSyncBlockNode } from '../utils/utils';
17
17
  export class ReferenceSyncBlockStoreManager {
18
18
  // Listeners for subscription changes (used by React components to know when to update)
19
19
 
20
+ // Track newly added sync blocks (resourceIds that were just subscribed to without cached data)
21
+
22
+ // Callback to notify when an unpublished sync block is detected
23
+
20
24
  constructor(dataProvider) {
21
25
  // Keeps track of addition and deletion of reference synced blocks on the document
22
26
  // This starts as true to always flush the cache when document is saved for the first time
@@ -36,6 +40,7 @@ export class ReferenceSyncBlockStoreManager {
36
40
  this.pendingCacheDeletions = new Map();
37
41
  this.graphqlSubscriptions = new Map();
38
42
  this.subscriptionChangeListeners = new Set();
43
+ this.newlyAddedSyncBlocks = new Set();
39
44
  }
40
45
 
41
46
  /**
@@ -124,6 +129,18 @@ export class ReferenceSyncBlockStoreManager {
124
129
  this.fetchSourceInfoExperience = getFetchSourceInfoExperience(fireAnalyticsEvent);
125
130
  this.saveExperience = getSaveReferenceExperience(fireAnalyticsEvent);
126
131
  }
132
+ setOnUnpublishedSyncBlockDetected(callback) {
133
+ this.onUnpublishedSyncBlockDetected = callback;
134
+ }
135
+
136
+ /**
137
+ * Mark a sync block as newly added to the document.
138
+ * This should be called when a sync block node is added via a transaction.
139
+ * @param resourceId - The resource ID of the newly added sync block
140
+ */
141
+ markAsNewlyAdded(resourceId) {
142
+ this.newlyAddedSyncBlocks.add(resourceId);
143
+ }
127
144
  generateResourceIdForReference(sourceId) {
128
145
  if (!this.dataProvider) {
129
146
  throw new Error('Data provider not set');
@@ -208,13 +225,18 @@ export class ReferenceSyncBlockStoreManager {
208
225
  */
209
226
  handleGraphQLSubscriptionUpdate(syncBlockInstance) {
210
227
  if (!syncBlockInstance.resourceId) {
211
- return;
228
+ throw new Error('Sync block instance provided to graphql subscription update missing resource id');
212
229
  }
213
230
  const existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
214
231
  const resolvedSyncBlockInstance = existingSyncBlock ? resolveSyncBlockInstance(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
215
232
  this.updateCache(resolvedSyncBlockInstance);
216
233
  if (!syncBlockInstance.error) {
234
+ var _this$fireAnalyticsEv4, _syncBlockInstance$da, _syncBlockInstance$da2;
235
+ (_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, fetchSuccessPayload(syncBlockInstance === null || syncBlockInstance === void 0 ? void 0 : syncBlockInstance.resourceId, syncBlockInstance === null || syncBlockInstance === void 0 ? void 0 : (_syncBlockInstance$da = syncBlockInstance.data) === null || _syncBlockInstance$da === void 0 ? void 0 : _syncBlockInstance$da.blockInstanceId, syncBlockInstance === null || syncBlockInstance === void 0 ? void 0 : (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product));
217
236
  this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
237
+ } else {
238
+ var _this$fireAnalyticsEv5, _syncBlockInstance$er;
239
+ (_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, fetchErrorPayload((_syncBlockInstance$er = syncBlockInstance.error) === null || _syncBlockInstance$er === void 0 ? void 0 : _syncBlockInstance$er.type, syncBlockInstance.resourceId));
218
240
  }
219
241
  }
220
242
 
@@ -290,8 +312,8 @@ export class ReferenceSyncBlockStoreManager {
290
312
  }
291
313
  }
292
314
  if (!sourceAri || !product || !blockInstanceId) {
293
- var _this$fireAnalyticsEv4;
294
- (_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing', resourceId));
315
+ var _this$fireAnalyticsEv6;
316
+ (_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing', resourceId));
295
317
  return Promise.resolve(undefined);
296
318
  }
297
319
  if (fg('platform_synced_block_dogfooding')) {
@@ -301,11 +323,11 @@ export class ReferenceSyncBlockStoreManager {
301
323
  const sourceInfoPromise = this.dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, sourceAri, product, this.fireAnalyticsEvent).then(sourceInfo => {
302
324
  if (!sourceInfo) {
303
325
  if (fg('platform_synced_block_dogfooding')) {
304
- var _this$fetchSourceInfo2, _this$fireAnalyticsEv5;
326
+ var _this$fetchSourceInfo2, _this$fireAnalyticsEv7;
305
327
  (_this$fetchSourceInfo2 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo2 === void 0 ? void 0 : _this$fetchSourceInfo2.failure({
306
328
  reason: 'No source info returned'
307
329
  });
308
- (_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, getSourceInfoErrorPayload('No source info returned', resourceId));
330
+ (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, getSourceInfoErrorPayload('No source info returned', resourceId));
309
331
  }
310
332
  return undefined;
311
333
  }
@@ -318,23 +340,23 @@ export class ReferenceSyncBlockStoreManager {
318
340
  var _this$fetchSourceInfo3;
319
341
  (_this$fetchSourceInfo3 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo3 === void 0 ? void 0 : _this$fetchSourceInfo3.success();
320
342
  } else {
321
- var _this$fetchSourceInfo4, _this$fireAnalyticsEv6;
343
+ var _this$fetchSourceInfo4, _this$fireAnalyticsEv8;
322
344
  (_this$fetchSourceInfo4 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo4 === void 0 ? void 0 : _this$fetchSourceInfo4.failure({
323
345
  reason: 'Missing title or url'
324
346
  });
325
- (_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, getSourceInfoErrorPayload('Missing title or url', resourceId));
347
+ (_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, getSourceInfoErrorPayload('Missing title or url', resourceId));
326
348
  }
327
349
  return sourceInfo;
328
350
  }
329
351
  }).catch(error => {
330
- var _this$fireAnalyticsEv7;
352
+ var _this$fireAnalyticsEv9;
331
353
  if (fg('platform_synced_block_dogfooding')) {
332
354
  var _this$fetchSourceInfo5;
333
355
  (_this$fetchSourceInfo5 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo5 === void 0 ? void 0 : _this$fetchSourceInfo5.failure({
334
356
  reason: error.message
335
357
  });
336
358
  }
337
- (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, getSourceInfoErrorPayload(error.message, resourceId));
359
+ (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, getSourceInfoErrorPayload(error.message, resourceId));
338
360
  return undefined;
339
361
  }).finally(() => {
340
362
  if (fg('platform_synced_block_dogfooding')) {
@@ -350,11 +372,11 @@ export class ReferenceSyncBlockStoreManager {
350
372
  this.syncBlockSourceInfoRequestsOld.set(resourceId, true);
351
373
  }
352
374
  } catch (error) {
353
- var _this$fireAnalyticsEv8;
375
+ var _this$fireAnalyticsEv0;
354
376
  logException(error, {
355
377
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
356
378
  });
357
- (_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, getSourceInfoErrorPayload(error.message, resourceId));
379
+ (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.call(this, getSourceInfoErrorPayload(error.message, resourceId));
358
380
  }
359
381
  return Promise.resolve(undefined);
360
382
  }
@@ -372,11 +394,12 @@ export class ReferenceSyncBlockStoreManager {
372
394
  // Don't fetch for not_found error since the source is already deleted
373
395
  const nodesToFetch = [];
374
396
  syncBlockNodes.forEach(node => {
397
+ var _existingSyncBlock$er;
375
398
  if (this.syncBlockFetchDataRequests.get(node.attrs.resourceId)) {
376
399
  return;
377
400
  }
378
401
  const existingSyncBlock = this.getFromCache(node.attrs.resourceId);
379
- if ((existingSyncBlock === null || existingSyncBlock === void 0 ? void 0 : existingSyncBlock.error) === SyncBlockError.NotFound) {
402
+ if ((existingSyncBlock === null || existingSyncBlock === void 0 ? void 0 : (_existingSyncBlock$er = existingSyncBlock.error) === null || _existingSyncBlock$er === void 0 ? void 0 : _existingSyncBlock$er.type) === SyncBlockError.NotFound) {
380
403
  return;
381
404
  }
382
405
  nodesToFetch.push(node);
@@ -402,26 +425,38 @@ export class ReferenceSyncBlockStoreManager {
402
425
  let hasUnexpectedError = false;
403
426
  let hasExpectedError = false;
404
427
  data.forEach(syncBlockInstance => {
428
+ var _resolvedSyncBlockIns;
405
429
  if (!syncBlockInstance.resourceId) {
406
- var _this$fireAnalyticsEv9;
407
- (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, fetchErrorPayload(syncBlockInstance.error || 'Returned sync block instance does not have resource id'));
430
+ var _this$fireAnalyticsEv1, _syncBlockInstance$er2;
431
+ (_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 ? void 0 : _this$fireAnalyticsEv1.call(this, fetchErrorPayload(((_syncBlockInstance$er2 = syncBlockInstance.error) === null || _syncBlockInstance$er2 === void 0 ? void 0 : _syncBlockInstance$er2.type) || 'Returned sync block instance does not have resource id'));
408
432
  return;
409
433
  }
410
434
  const existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
411
435
  const resolvedSyncBlockInstance = existingSyncBlock ? resolveSyncBlockInstance(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
412
436
  this.updateCache(resolvedSyncBlockInstance);
437
+
438
+ // Check if this is a newly added unpublished sync block and notify
439
+ // Only trigger for sync blocks that were just added (not refreshed or loaded on page init)
440
+ if (!syncBlockInstance.error && ((_resolvedSyncBlockIns = resolvedSyncBlockInstance.data) === null || _resolvedSyncBlockIns === void 0 ? void 0 : _resolvedSyncBlockIns.status) === 'unpublished' && this.newlyAddedSyncBlocks.has(syncBlockInstance.resourceId) && this.onUnpublishedSyncBlockDetected && fg('platform_synced_block_dogfooding')) {
441
+ // Remove from newly added set after checking to prevent duplicate flags
442
+ this.newlyAddedSyncBlocks.delete(syncBlockInstance.resourceId);
443
+ this.onUnpublishedSyncBlockDetected(resolvedSyncBlockInstance.resourceId);
444
+ } else if (this.newlyAddedSyncBlocks.has(syncBlockInstance.resourceId)) {
445
+ // Remove from newly added set even if not unpublished (to clean up)
446
+ this.newlyAddedSyncBlocks.delete(syncBlockInstance.resourceId);
447
+ }
413
448
  if (syncBlockInstance.error) {
414
- var _this$fireAnalyticsEv0;
415
- (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.call(this, fetchErrorPayload(syncBlockInstance.error, syncBlockInstance.resourceId));
416
- if (syncBlockInstance.error === SyncBlockError.NotFound || syncBlockInstance.error === SyncBlockError.Forbidden) {
449
+ var _this$fireAnalyticsEv10;
450
+ (_this$fireAnalyticsEv10 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv10 === void 0 ? void 0 : _this$fireAnalyticsEv10.call(this, fetchErrorPayload(syncBlockInstance.error.type, syncBlockInstance.resourceId));
451
+ if (syncBlockInstance.error.type === SyncBlockError.NotFound || syncBlockInstance.error.type === SyncBlockError.Forbidden) {
417
452
  hasExpectedError = true;
418
453
  } else if (syncBlockInstance.error) {
419
454
  hasUnexpectedError = true;
420
455
  }
421
456
  return;
422
457
  } else if (fg('platform_synced_block_dogfooding')) {
423
- var _this$fireAnalyticsEv1, _syncBlockInstance$da, _syncBlockInstance$da2;
424
- (_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 ? void 0 : _this$fireAnalyticsEv1.call(this, 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));
458
+ var _this$fireAnalyticsEv11, _syncBlockInstance$da3, _syncBlockInstance$da4;
459
+ (_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, fetchSuccessPayload(syncBlockInstance.resourceId, (_syncBlockInstance$da3 = syncBlockInstance.data) === null || _syncBlockInstance$da3 === void 0 ? void 0 : _syncBlockInstance$da3.blockInstanceId, (_syncBlockInstance$da4 = syncBlockInstance.data) === null || _syncBlockInstance$da4 === void 0 ? void 0 : _syncBlockInstance$da4.product));
425
460
  }
426
461
  this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
427
462
  });
@@ -521,11 +556,11 @@ export class ReferenceSyncBlockStoreManager {
521
556
  callback(cachedData);
522
557
  } else {
523
558
  this.fetchSyncBlocksData([syncBlockNode]).catch(error => {
524
- var _this$fireAnalyticsEv10;
559
+ var _this$fireAnalyticsEv12;
525
560
  logException(error, {
526
561
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
527
562
  });
528
- (_this$fireAnalyticsEv10 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv10 === void 0 ? void 0 : _this$fireAnalyticsEv10.call(this, fetchErrorPayload(error.message, resourceId));
563
+ (_this$fireAnalyticsEv12 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv12 === void 0 ? void 0 : _this$fireAnalyticsEv12.call(this, fetchErrorPayload(error.message, resourceId));
529
564
  });
530
565
  }
531
566
 
@@ -618,11 +653,11 @@ export class ReferenceSyncBlockStoreManager {
618
653
  }
619
654
  return this.subscribeToSyncBlock(resourceId, localId, callback);
620
655
  } catch (error) {
621
- var _this$fireAnalyticsEv11;
656
+ var _this$fireAnalyticsEv13;
622
657
  logException(error, {
623
658
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
624
659
  });
625
- (_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, fetchErrorPayload(error.message));
660
+ (_this$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, fetchErrorPayload(error.message));
626
661
  return () => {};
627
662
  }
628
663
  }
@@ -642,12 +677,12 @@ export class ReferenceSyncBlockStoreManager {
642
677
  }
643
678
  getProviderFactory(resourceId) {
644
679
  if (!this.dataProvider) {
645
- var _this$fireAnalyticsEv12;
680
+ var _this$fireAnalyticsEv14;
646
681
  const error = new Error('Data provider not set');
647
682
  logException(error, {
648
683
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
649
684
  });
650
- (_this$fireAnalyticsEv12 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv12 === void 0 ? void 0 : _this$fireAnalyticsEv12.call(this, fetchErrorPayload(error.message));
685
+ (_this$fireAnalyticsEv14 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv14 === void 0 ? void 0 : _this$fireAnalyticsEv14.call(this, fetchErrorPayload(error.message));
651
686
  return undefined;
652
687
  }
653
688
  const {
@@ -677,11 +712,11 @@ export class ReferenceSyncBlockStoreManager {
677
712
  try {
678
713
  this.retrieveDynamicProviders(resourceId, providerFactory, providerCreator);
679
714
  } catch (error) {
680
- var _this$fireAnalyticsEv13;
715
+ var _this$fireAnalyticsEv15;
681
716
  logException(error, {
682
717
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
683
718
  });
684
- (_this$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, fetchErrorPayload(error.message, resourceId));
719
+ (_this$fireAnalyticsEv15 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv15 === void 0 ? void 0 : _this$fireAnalyticsEv15.call(this, fetchErrorPayload(error.message, resourceId));
685
720
  }
686
721
  }
687
722
  return providerFactory;
@@ -740,8 +775,8 @@ export class ReferenceSyncBlockStoreManager {
740
775
  return;
741
776
  }
742
777
  if (!syncBlock.data.sourceAri || !syncBlock.data.product) {
743
- var _this$fireAnalyticsEv14;
744
- (_this$fireAnalyticsEv14 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv14 === void 0 ? void 0 : _this$fireAnalyticsEv14.call(this, fetchErrorPayload('Sync block source ari or product not found'));
778
+ var _this$fireAnalyticsEv16;
779
+ (_this$fireAnalyticsEv16 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv16 === void 0 ? void 0 : _this$fireAnalyticsEv16.call(this, fetchErrorPayload('Sync block source ari or product not found'));
745
780
  return;
746
781
  }
747
782
  const parentInfo = this.dataProvider.retrieveSyncBlockParentInfo((_syncBlock$data2 = syncBlock.data) === null || _syncBlock$data2 === void 0 ? void 0 : _syncBlock$data2.sourceAri, (_syncBlock$data3 = syncBlock.data) === null || _syncBlock$data3 === void 0 ? void 0 : _syncBlock$data3.product);
@@ -830,7 +865,7 @@ export class ReferenceSyncBlockStoreManager {
830
865
  }
831
866
  const updateResult = await this.dataProvider.updateReferenceData(blocks);
832
867
  if (!updateResult.success) {
833
- var _this$fireAnalyticsEv15;
868
+ var _this$fireAnalyticsEv17;
834
869
  success = false;
835
870
  if (fg('platform_synced_block_dogfooding')) {
836
871
  var _this$saveExperience2;
@@ -838,10 +873,10 @@ export class ReferenceSyncBlockStoreManager {
838
873
  reason: updateResult.error || 'Failed to update reference synced blocks on the document'
839
874
  });
840
875
  }
841
- (_this$fireAnalyticsEv15 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv15 === void 0 ? void 0 : _this$fireAnalyticsEv15.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document'));
876
+ (_this$fireAnalyticsEv17 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv17 === void 0 ? void 0 : _this$fireAnalyticsEv17.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document'));
842
877
  }
843
878
  } catch (error) {
844
- var _this$fireAnalyticsEv16;
879
+ var _this$fireAnalyticsEv18;
845
880
  success = false;
846
881
  logException(error, {
847
882
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
@@ -852,7 +887,7 @@ export class ReferenceSyncBlockStoreManager {
852
887
  reason: error.message
853
888
  });
854
889
  }
855
- (_this$fireAnalyticsEv16 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv16 === void 0 ? void 0 : _this$fireAnalyticsEv16.call(this, updateReferenceErrorPayload(error.message));
890
+ (_this$fireAnalyticsEv18 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv18 === void 0 ? void 0 : _this$fireAnalyticsEv18.call(this, updateReferenceErrorPayload(error.message));
856
891
  } finally {
857
892
  if (!success) {
858
893
  // set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
@@ -884,13 +919,13 @@ export class ReferenceSyncBlockStoreManager {
884
919
  });
885
920
  this.providerFactories.clear();
886
921
  (_this$saveExperience5 = this.saveExperience) === null || _this$saveExperience5 === void 0 ? void 0 : _this$saveExperience5.abort({
887
- reason: 'editor-destroyed'
922
+ reason: 'editorDestroyed'
888
923
  });
889
924
  (_this$fetchExperience5 = this.fetchExperience) === null || _this$fetchExperience5 === void 0 ? void 0 : _this$fetchExperience5.abort({
890
- reason: 'editor-destroyed'
925
+ reason: 'editorDestroyed'
891
926
  });
892
927
  (_this$fetchSourceInfo6 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo6 === void 0 ? void 0 : _this$fetchSourceInfo6.abort({
893
- reason: 'editor-destroyed'
928
+ reason: 'editorDestroyed'
894
929
  });
895
930
  this.fireAnalyticsEvent = undefined;
896
931
  }
@@ -2,8 +2,8 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { logException } from '@atlaskit/editor-common/monitoring';
3
3
  import { fg } from '@atlaskit/platform-feature-flags';
4
4
  import { SyncBlockError } from '../common/types';
5
- import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload, getSourceInfoErrorPayload, updateSuccessPayload, createSuccessPayload, deleteSuccessPayload } from '../utils/errorHandling';
6
- import { getCreateSourceExperience, getDeleteSourceExperience, getSaveSourceExperience } from '../utils/experienceTracking';
5
+ import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload, getSourceInfoErrorPayload, updateSuccessPayload, createSuccessPayload, deleteSuccessPayload, fetchReferencesErrorPayload } from '../utils/errorHandling';
6
+ import { getCreateSourceExperience, getDeleteSourceExperience, getSaveSourceExperience, getFetchSourceInfoExperience } from '../utils/experienceTracking';
7
7
  import { convertSyncBlockPMNodeToSyncBlockData } from '../utils/utils';
8
8
  // A store manager responsible for the lifecycle and state management of source sync blocks in an editor instance.
9
9
  // Designed to manage local in-memory state and synchronize with an external data provider.
@@ -26,6 +26,7 @@ export class SourceSyncBlockStoreManager {
26
26
  this.createExperience = getCreateSourceExperience(fireAnalyticsEvent);
27
27
  this.saveExperience = getSaveSourceExperience(fireAnalyticsEvent);
28
28
  this.deleteExperience = getDeleteSourceExperience(fireAnalyticsEvent);
29
+ this.fetchSourceInfoExperience = getFetchSourceInfoExperience(fireAnalyticsEvent);
29
30
  }
30
31
  isSourceBlock(node) {
31
32
  return node.type.name === 'bodiedSyncBlock';
@@ -103,7 +104,6 @@ export class SourceSyncBlockStoreManager {
103
104
  var _this$saveExperience;
104
105
  (_this$saveExperience = this.saveExperience) === null || _this$saveExperience === void 0 ? void 0 : _this$saveExperience.start({});
105
106
  }
106
- ;
107
107
  const writeResults = await this.dataProvider.writeNodesData(bodiedSyncBlockNodes, bodiedSyncBlockData);
108
108
  writeResults.forEach(result => {
109
109
  // set isDirty to true for cases where it failed to save the sync block to the BE
@@ -125,7 +125,6 @@ export class SourceSyncBlockStoreManager {
125
125
  }
126
126
  });
127
127
  }
128
- ;
129
128
  return true;
130
129
  } else {
131
130
  if (fg('platform_synced_block_dogfooding')) {
@@ -275,7 +274,7 @@ export class SourceSyncBlockStoreManager {
275
274
  (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, createErrorPayload(error.message));
276
275
  }
277
276
  }
278
- async delete(syncBlockIds, onDelete, onDeleteCompleted) {
277
+ async delete(syncBlockIds, onDelete, onDeleteCompleted, reason) {
279
278
  try {
280
279
  if (!this.dataProvider) {
281
280
  throw new Error('Data provider not set');
@@ -287,7 +286,7 @@ export class SourceSyncBlockStoreManager {
287
286
  var _this$deleteExperienc;
288
287
  (_this$deleteExperienc = this.deleteExperience) === null || _this$deleteExperienc === void 0 ? void 0 : _this$deleteExperienc.start({});
289
288
  }
290
- const results = await this.dataProvider.deleteNodesData(syncBlockIds.map(attrs => attrs.resourceId));
289
+ const results = await this.dataProvider.deleteNodesData(syncBlockIds.map(attrs => attrs.resourceId), reason);
291
290
  let callback;
292
291
  const isDeleteSuccessful = results.every(result => result.success);
293
292
  onDeleteCompleted(isDeleteSuccessful);
@@ -351,10 +350,11 @@ export class SourceSyncBlockStoreManager {
351
350
  const {
352
351
  syncBlockIds,
353
352
  onDelete,
354
- onDeleteCompleted
353
+ onDeleteCompleted,
354
+ deletionReason
355
355
  } = this.deletionRetryInfo;
356
356
  if (this.confirmationCallback) {
357
- await this.delete(syncBlockIds, onDelete, onDeleteCompleted);
357
+ await this.delete(syncBlockIds, onDelete, onDeleteCompleted, deletionReason);
358
358
  }
359
359
  }
360
360
  clearPendingDeletion() {
@@ -370,18 +370,19 @@ export class SourceSyncBlockStoreManager {
370
370
  * @param onDeleteCompleted - The callback for after the deletion is saved to BE (whether successful or not)
371
371
  * @param destroyCallback - The callback to clear any reference stored for deletion (regardless if deletion is completed or abort)
372
372
  */
373
- async deleteSyncBlocksWithConfirmation(syncBlockIds, onDelete, onDeleteCompleted, destroyCallback) {
373
+ async deleteSyncBlocksWithConfirmation(syncBlockIds, deletionReason, onDelete, onDeleteCompleted, destroyCallback) {
374
374
  if (this.confirmationCallback) {
375
- const confirmed = await this.confirmationCallback(syncBlockIds.length);
375
+ const confirmed = await this.confirmationCallback(syncBlockIds, deletionReason);
376
376
  if (confirmed) {
377
- const isDeleteSuccessful = await this.delete(syncBlockIds, onDelete, onDeleteCompleted);
377
+ const isDeleteSuccessful = await this.delete(syncBlockIds, onDelete, onDeleteCompleted, deletionReason);
378
378
  if (!isDeleteSuccessful) {
379
379
  // If deletion failed, save deletion info for potential retry
380
380
  this.deletionRetryInfo = {
381
381
  syncBlockIds,
382
382
  onDelete,
383
383
  onDeleteCompleted,
384
- destroyCallback
384
+ destroyCallback,
385
+ deletionReason
385
386
  };
386
387
  } else {
387
388
  destroyCallback();
@@ -396,7 +397,24 @@ export class SourceSyncBlockStoreManager {
396
397
  if (!this.dataProvider) {
397
398
  throw new Error('Data provider not set');
398
399
  }
399
- return this.dataProvider.fetchSyncBlockSourceInfo(localId, undefined, undefined, this.fireAnalyticsEvent);
400
+ if (fg('platform_synced_block_dogfooding')) {
401
+ var _this$fetchSourceInfo;
402
+ (_this$fetchSourceInfo = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo === void 0 ? void 0 : _this$fetchSourceInfo.start();
403
+ }
404
+ return this.dataProvider.fetchSyncBlockSourceInfo(localId, undefined, undefined, this.fireAnalyticsEvent).then(sourceInfo => {
405
+ if (fg('platform_synced_block_dogfooding')) {
406
+ if (!sourceInfo) {
407
+ var _this$fetchSourceInfo2;
408
+ (_this$fetchSourceInfo2 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo2 === void 0 ? void 0 : _this$fetchSourceInfo2.failure({
409
+ reason: "No source info returned"
410
+ });
411
+ } else {
412
+ var _this$fetchSourceInfo3;
413
+ (_this$fetchSourceInfo3 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo3 === void 0 ? void 0 : _this$fetchSourceInfo3.success();
414
+ }
415
+ }
416
+ return sourceInfo;
417
+ });
400
418
  } catch (error) {
401
419
  var _this$fireAnalyticsEv13;
402
420
  logException(error, {
@@ -406,21 +424,41 @@ export class SourceSyncBlockStoreManager {
406
424
  return Promise.resolve(undefined);
407
425
  }
408
426
  }
427
+ fetchReferences(resourceId) {
428
+ try {
429
+ if (!this.dataProvider) {
430
+ throw new Error('Data provider not set');
431
+ }
432
+ return this.dataProvider.fetchReferences(resourceId, true);
433
+ } catch (error) {
434
+ var _this$fireAnalyticsEv14;
435
+ logException(error, {
436
+ location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
437
+ });
438
+ (_this$fireAnalyticsEv14 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv14 === void 0 ? void 0 : _this$fireAnalyticsEv14.call(this, fetchReferencesErrorPayload(error.message));
439
+ return Promise.resolve({
440
+ error: SyncBlockError.Errored
441
+ });
442
+ }
443
+ }
409
444
  destroy() {
410
- var _this$saveExperience4, _this$createExperienc5, _this$deleteExperienc4;
445
+ var _this$saveExperience4, _this$createExperienc5, _this$deleteExperienc4, _this$fetchSourceInfo4;
411
446
  this.syncBlockCache.clear();
412
447
  this.confirmationCallback = undefined;
413
448
  this.pendingResourceId = undefined;
414
449
  this.creationCallback = undefined;
415
450
  this.dataProvider = undefined;
416
451
  (_this$saveExperience4 = this.saveExperience) === null || _this$saveExperience4 === void 0 ? void 0 : _this$saveExperience4.abort({
417
- reason: 'editor-destroyed'
452
+ reason: 'editorDestroyed'
418
453
  });
419
454
  (_this$createExperienc5 = this.createExperience) === null || _this$createExperienc5 === void 0 ? void 0 : _this$createExperienc5.abort({
420
- reason: 'editor-destroyed'
455
+ reason: 'editorDestroyed'
421
456
  });
422
457
  (_this$deleteExperienc4 = this.deleteExperience) === null || _this$deleteExperienc4 === void 0 ? void 0 : _this$deleteExperienc4.abort({
423
- reason: 'editor-destroyed'
458
+ reason: 'editorDestroyed'
459
+ });
460
+ (_this$fetchSourceInfo4 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo4 === void 0 ? void 0 : _this$fetchSourceInfo4.abort({
461
+ reason: 'editorDestroyed'
424
462
  });
425
463
  this.clearPendingDeletion();
426
464
  }
@@ -1,8 +1,10 @@
1
1
  import { useMemo } from 'react';
2
2
  import { logException } from '@atlaskit/editor-common/monitoring';
3
+ import { fg } from '@atlaskit/platform-feature-flags';
3
4
  import { getProductFromSourceAri } from '../clients/block-service/ari';
4
5
  import { SyncBlockError } from '../common/types';
5
6
  import { fetchReferencesErrorPayload } from '../utils/errorHandling';
7
+ import { getFetchReferencesExperience, getFetchSourceInfoExperience } from '../utils/experienceTracking';
6
8
  import { ReferenceSyncBlockStoreManager } from './referenceSyncBlockStoreManager';
7
9
  import { SourceSyncBlockStoreManager } from './sourceSyncBlockStoreManager';
8
10
 
@@ -21,30 +23,51 @@ export class SyncBlockStoreManager {
21
23
  }
22
24
  async fetchReferencesSourceInfo(resourceId, blockInstanceId, isSourceSyncBlock) {
23
25
  try {
24
- var _response$references;
26
+ var _this$fetchReferences, _response$references, _this$fetchReferences5;
25
27
  if (!this.dataProvider) {
26
28
  throw new Error('Data provider not set');
27
29
  }
30
+ (_this$fetchReferences = this.fetchReferencesExperience) === null || _this$fetchReferences === void 0 ? void 0 : _this$fetchReferences.start();
28
31
  const response = await this.dataProvider.fetchReferences(resourceId, isSourceSyncBlock);
29
32
  if (response.error) {
33
+ var _this$fetchReferences2;
34
+ (_this$fetchReferences2 = this.fetchReferencesExperience) === null || _this$fetchReferences2 === void 0 ? void 0 : _this$fetchReferences2.failure({
35
+ reason: response.error
36
+ });
30
37
  return {
31
38
  error: response.error
32
39
  };
33
40
  }
34
41
  if (!response.references || ((_response$references = response.references) === null || _response$references === void 0 ? void 0 : _response$references.length) === 0) {
35
42
  // No reference found
43
+ if (isSourceSyncBlock) {
44
+ var _this$fetchReferences3;
45
+ (_this$fetchReferences3 = this.fetchReferencesExperience) === null || _this$fetchReferences3 === void 0 ? void 0 : _this$fetchReferences3.success();
46
+ } else {
47
+ var _this$fetchReferences4;
48
+ (_this$fetchReferences4 = this.fetchReferencesExperience) === null || _this$fetchReferences4 === void 0 ? void 0 : _this$fetchReferences4.failure({
49
+ reason: 'No references found for reference synced block'
50
+ });
51
+ }
36
52
  return isSourceSyncBlock ? {
37
53
  references: []
38
54
  } : {
39
55
  error: SyncBlockError.Errored
40
56
  };
41
57
  }
58
+ (_this$fetchReferences5 = this.fetchReferencesExperience) === null || _this$fetchReferences5 === void 0 ? void 0 : _this$fetchReferences5.success();
42
59
  const sourceInfoPromises = response.references.map(async reference => {
43
- var _this$dataProvider;
44
- const sourceInfo = await ((_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.fetchSyncBlockSourceInfo(blockInstanceId, reference.documentAri, getProductFromSourceAri(reference.documentAri), this.fireAnalyticsEvent, reference.hasAccess, 'view'));
60
+ var _this$fetchSourceInfo, _this$dataProvider, _this$fetchSourceInfo3;
61
+ (_this$fetchSourceInfo = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo === void 0 ? void 0 : _this$fetchSourceInfo.start();
62
+ const sourceInfo = await ((_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.fetchSyncBlockSourceInfo(reference.blockInstanceId || '', reference.documentAri, getProductFromSourceAri(reference.documentAri), this.fireAnalyticsEvent, reference.hasAccess, 'view'));
45
63
  if (!sourceInfo) {
64
+ var _this$fetchSourceInfo2;
65
+ (_this$fetchSourceInfo2 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo2 === void 0 ? void 0 : _this$fetchSourceInfo2.failure({
66
+ reason: `no source info returned for ari: ${reference.documentAri}`
67
+ });
46
68
  return undefined;
47
69
  }
70
+ (_this$fetchSourceInfo3 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo3 === void 0 ? void 0 : _this$fetchSourceInfo3.success();
48
71
  return {
49
72
  ...sourceInfo,
50
73
  onSameDocument: reference.onSameDocument,
@@ -81,6 +104,10 @@ export class SyncBlockStoreManager {
81
104
  this.fireAnalyticsEvent = fireAnalyticsEvent;
82
105
  this.referenceSyncBlockStoreManager.setFireAnalyticsEvent(fireAnalyticsEvent);
83
106
  this.sourceSyncBlockStoreManager.setFireAnalyticsEvent(fireAnalyticsEvent);
107
+ if (fg('platform_synced_block_dogfooding')) {
108
+ this.fetchReferencesExperience = getFetchReferencesExperience(fireAnalyticsEvent);
109
+ this.fetchSourceInfoExperience = getFetchSourceInfoExperience(fireAnalyticsEvent);
110
+ }
84
111
  }
85
112
  get referenceManager() {
86
113
  return this.referenceSyncBlockStoreManager;
@@ -89,8 +116,15 @@ export class SyncBlockStoreManager {
89
116
  return this.sourceSyncBlockStoreManager;
90
117
  }
91
118
  destroy() {
119
+ var _this$fetchReferences6, _this$fetchSourceInfo4;
92
120
  this.referenceSyncBlockStoreManager.destroy();
93
121
  this.sourceSyncBlockStoreManager.destroy();
122
+ (_this$fetchReferences6 = this.fetchReferencesExperience) === null || _this$fetchReferences6 === void 0 ? void 0 : _this$fetchReferences6.abort({
123
+ reason: 'editorDestroyed'
124
+ });
125
+ (_this$fetchSourceInfo4 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo4 === void 0 ? void 0 : _this$fetchSourceInfo4.abort({
126
+ reason: 'editorDestroyed'
127
+ });
94
128
  }
95
129
  }
96
130
  const createSyncBlockStoreManager = dataProvider => {
@@ -110,4 +110,21 @@ export const getCreateSourceExperience = fireAnalyticsEvent => {
110
110
  durationMs: TIMEOUT_DURATION
111
111
  })]
112
112
  });
113
+ };
114
+
115
+ /**
116
+ * This experience tracks when a source sync block is created and registered to the BE.
117
+ *
118
+ * Start: When the fetchSourceInfo function is called.
119
+ * Success: When the fetching the data is successful within the timeout duration of start.
120
+ * Failure: When the timeout duration passes without the data being successfully fetched, or the fetch fails
121
+ */
122
+ export const getFetchReferencesExperience = fireAnalyticsEvent => {
123
+ return new Experience(EXPERIENCE_ID.ASYNC_OPERATION, {
124
+ action: ACTION.SYNCED_BLOCK_FETCH_REFERENCES,
125
+ dispatchAnalyticsEvent: createExperienceDispatcher(fireAnalyticsEvent),
126
+ checks: [new ExperienceCheckTimeout({
127
+ durationMs: TIMEOUT_DURATION
128
+ })]
129
+ });
113
130
  };
@@ -16,8 +16,9 @@ export const resolveSyncBlockInstance = (oldResult, newResult) => {
16
16
  if (!oldResult.data) {
17
17
  return newResult;
18
18
  } else if (!newResult.data) {
19
+ var _newResult$error, _newResult$error2;
19
20
  // return the old result if there was an error, e.g. network error, but not if not found or forbidden
20
- if (newResult.error === SyncBlockError.NotFound || newResult.error === SyncBlockError.Forbidden) {
21
+ if (((_newResult$error = newResult.error) === null || _newResult$error === void 0 ? void 0 : _newResult$error.type) === SyncBlockError.NotFound || ((_newResult$error2 = newResult.error) === null || _newResult$error2 === void 0 ? void 0 : _newResult$error2.type) === SyncBlockError.Forbidden) {
21
22
  return newResult;
22
23
  } else {
23
24
  return oldResult;