@atlaskit/editor-synced-block-provider 10.0.3 → 10.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/common/types.js +2 -3
- package/dist/cjs/hooks/useFetchSyncBlockData.js +4 -4
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +27 -56
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +22 -41
- package/dist/cjs/store-manager/syncBlockBatchFetcher.js +6 -12
- package/dist/cjs/store-manager/syncBlockProviderFactoryManager.js +3 -3
- package/dist/cjs/store-manager/syncBlockStoreManager.js +1 -5
- package/dist/cjs/store-manager/syncBlockSubscriptionManager.js +20 -85
- package/dist/cjs/utils/errorHandling.js +13 -32
- package/dist/es2019/common/types.js +2 -3
- package/dist/es2019/hooks/useFetchSyncBlockData.js +4 -5
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +26 -50
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +23 -42
- package/dist/es2019/store-manager/syncBlockBatchFetcher.js +6 -12
- package/dist/es2019/store-manager/syncBlockProviderFactoryManager.js +3 -3
- package/dist/es2019/store-manager/syncBlockStoreManager.js +1 -5
- package/dist/es2019/store-manager/syncBlockSubscriptionManager.js +25 -81
- package/dist/es2019/utils/errorHandling.js +13 -32
- package/dist/esm/common/types.js +2 -3
- package/dist/esm/hooks/useFetchSyncBlockData.js +4 -4
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +27 -56
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +22 -41
- package/dist/esm/store-manager/syncBlockBatchFetcher.js +6 -12
- package/dist/esm/store-manager/syncBlockProviderFactoryManager.js +3 -3
- package/dist/esm/store-manager/syncBlockStoreManager.js +1 -5
- package/dist/esm/store-manager/syncBlockSubscriptionManager.js +20 -85
- package/dist/esm/utils/errorHandling.js +13 -32
- package/dist/types/common/types.d.ts +2 -3
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +3 -3
- package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +5 -7
- package/dist/types/store-manager/syncBlockSubscriptionManager.d.ts +2 -5
- package/dist/types/utils/errorHandling.d.ts +11 -24
- package/package.json +3 -15
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
3
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
3
|
import { SyncBlockError } from '../common/types';
|
|
5
4
|
import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload, getSourceInfoErrorPayload, updateSuccessPayload, createSuccessPayload, createSuccessOperationalPayload, addContentSuccessPayload, deleteSuccessPayload, fetchReferencesErrorPayload, buildErrorAttribution } from '../utils/errorHandling';
|
|
6
5
|
import { getCreateSourceExperience, getDeleteSourceExperience, getSaveSourceExperience, getFetchSourceInfoExperience } from '../utils/experienceTracking';
|
|
@@ -63,8 +62,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
63
62
|
_defineProperty(this, "awaitingFirstContent", new Set());
|
|
64
63
|
/**
|
|
65
64
|
* resourceId -> timestamp (ms) of the last `syncedBlockDelete` emission, used
|
|
66
|
-
* to suppress duplicates within {@link DELETE_DEDUPE_WINDOW_MS}.
|
|
67
|
-
* behind `platform_editor_blocks_patch_4`.
|
|
65
|
+
* to suppress duplicates within {@link DELETE_DEDUPE_WINDOW_MS}.
|
|
68
66
|
*/
|
|
69
67
|
_defineProperty(this, "recentDeleteEmissions", new Map());
|
|
70
68
|
_defineProperty(this, "setPendingDeletion", (Ids, value) => {
|
|
@@ -137,10 +135,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
137
135
|
} = syncBlockNode.attrs;
|
|
138
136
|
if (!localId || !resourceId) {
|
|
139
137
|
// Identifiers not populated yet: benign timing case, skip as a no-op.
|
|
140
|
-
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
throw new Error('Local ID or resource ID is not set');
|
|
138
|
+
return false;
|
|
144
139
|
}
|
|
145
140
|
const cachedBlock = this.syncBlockCache.get(resourceId);
|
|
146
141
|
|
|
@@ -282,10 +277,9 @@ export class SourceSyncBlockStoreManager {
|
|
|
282
277
|
} else {
|
|
283
278
|
var _this$saveExperience3;
|
|
284
279
|
(_this$saveExperience3 = this.saveExperience) === null || _this$saveExperience3 === void 0 ? void 0 : _this$saveExperience3.failure();
|
|
285
|
-
const attributionEnabled = fg('platform_editor_blocks_patch_3');
|
|
286
280
|
writeResults.filter(result => !result.resourceId || result.error).forEach(result => {
|
|
287
281
|
var _this$fireAnalyticsEv3;
|
|
288
|
-
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, updateErrorPayload(result.error || 'Failed to write data', result.resourceId, getSourceProductFromResourceIdSafe(result.resourceId), buildErrorAttribution(
|
|
282
|
+
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, updateErrorPayload(result.error || 'Failed to write data', result.resourceId, getSourceProductFromResourceIdSafe(result.resourceId), buildErrorAttribution(result.error, result.statusCode)));
|
|
289
283
|
});
|
|
290
284
|
return false;
|
|
291
285
|
}
|
|
@@ -296,7 +290,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
296
290
|
});
|
|
297
291
|
// Top-level flush failure is not tied to a single resourceId. There is no structured
|
|
298
292
|
// SyncBlockError/status here, so the attribution `reason` falls back to `unknown`.
|
|
299
|
-
(_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, updateErrorPayload(error.message, undefined, undefined, buildErrorAttribution(
|
|
293
|
+
(_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, updateErrorPayload(error.message, undefined, undefined, buildErrorAttribution()));
|
|
300
294
|
return false;
|
|
301
295
|
} finally {
|
|
302
296
|
var _this$flushCompletion;
|
|
@@ -368,15 +362,12 @@ export class SourceSyncBlockStoreManager {
|
|
|
368
362
|
(_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, createErrorPayload('creation complete callback missing', resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
369
363
|
}
|
|
370
364
|
if (success) {
|
|
371
|
-
var _this$fireAnalyticsEv6;
|
|
365
|
+
var _this$fireAnalyticsEv6, _this$fireAnalyticsEv7, _this$syncBlockCache$2;
|
|
372
366
|
const sourceProduct = getSourceProductFromResourceIdSafe(resourceId);
|
|
373
367
|
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, createSuccessPayload(resourceId || '', sourceProduct));
|
|
374
368
|
// Operational create-success event with the join key + creation-type
|
|
375
369
|
// signals (inputMethod / createdEmpty) captured at the command layer.
|
|
376
|
-
|
|
377
|
-
var _this$fireAnalyticsEv7, _this$syncBlockCache$2;
|
|
378
|
-
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, createSuccessOperationalPayload(resourceId || '', (_this$syncBlockCache$2 = this.syncBlockCache.get(resourceId)) === null || _this$syncBlockCache$2 === void 0 ? void 0 : _this$syncBlockCache$2.blockInstanceId, sourceProduct, this.creationEnrichment.get(resourceId)));
|
|
379
|
-
}
|
|
370
|
+
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, createSuccessOperationalPayload(resourceId || '', (_this$syncBlockCache$2 = this.syncBlockCache.get(resourceId)) === null || _this$syncBlockCache$2 === void 0 ? void 0 : _this$syncBlockCache$2.blockInstanceId, sourceProduct, this.creationEnrichment.get(resourceId)));
|
|
380
371
|
} else {
|
|
381
372
|
var _this$fireAnalyticsEv8;
|
|
382
373
|
// Delete the node from cache if fail to create so it's not flushed to BE
|
|
@@ -395,16 +386,12 @@ export class SourceSyncBlockStoreManager {
|
|
|
395
386
|
* Fire the first-content-added event once when a block created empty this
|
|
396
387
|
* session first gains content. The caller detects the in-block edit; this owns
|
|
397
388
|
* dedupe + emission (fires at most once per block, only for empty→content).
|
|
398
|
-
* Gated behind `platform_editor_blocks_patch_4`.
|
|
399
389
|
*/
|
|
400
390
|
maybeEmitFirstContentAdded(resourceId, blockInstanceId) {
|
|
401
391
|
var _this$fireAnalyticsEv9;
|
|
402
392
|
if (this.viewMode === 'view') {
|
|
403
393
|
return;
|
|
404
394
|
}
|
|
405
|
-
if (!fg('platform_editor_blocks_patch_4')) {
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
395
|
// `delete` returns false when the id was not tracked (already emitted, or
|
|
409
396
|
// the block was not created empty this session), so this both dedupes and
|
|
410
397
|
// scopes emission to genuine first-content transitions in one check.
|
|
@@ -501,7 +488,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
501
488
|
(_this$createExperienc3 = this.createExperience) === null || _this$createExperienc3 === void 0 ? void 0 : _this$createExperienc3.failure({
|
|
502
489
|
reason: result.error || 'Failed to create bodied sync block'
|
|
503
490
|
});
|
|
504
|
-
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.call(this, createErrorPayload(result.error || 'Failed to create bodied sync block', resourceId, getSourceProductFromResourceIdSafe(resourceId), buildErrorAttribution(
|
|
491
|
+
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.call(this, createErrorPayload(result.error || 'Failed to create bodied sync block', resourceId, getSourceProductFromResourceIdSafe(resourceId), buildErrorAttribution(result.error, result.statusCode)));
|
|
505
492
|
}
|
|
506
493
|
}).catch(error => {
|
|
507
494
|
var _this$createExperienc4, _this$fireAnalyticsEv1;
|
|
@@ -542,19 +529,14 @@ export class SourceSyncBlockStoreManager {
|
|
|
542
529
|
}
|
|
543
530
|
|
|
544
531
|
/**
|
|
545
|
-
* Emit the `syncedBlockDelete` success event.
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
532
|
+
* Emit the `syncedBlockDelete` success event. Attaches `deletionReason`,
|
|
533
|
+
* `mechanism` and `blockInstanceId`, and suppresses repeat emissions within
|
|
534
|
+
* {@link DELETE_DEDUPE_WINDOW_MS}. Must run while the cache entry still exists
|
|
535
|
+
* so `blockInstanceId` is available.
|
|
549
536
|
*/
|
|
550
537
|
emitDeleteSuccess(resourceId, reason, mechanism) {
|
|
551
|
-
var _this$syncBlockCache$3, _this$
|
|
538
|
+
var _this$syncBlockCache$3, _this$fireAnalyticsEv11;
|
|
552
539
|
const sourceProduct = getSourceProductFromResourceIdSafe(resourceId);
|
|
553
|
-
if (!fg('platform_editor_blocks_patch_4')) {
|
|
554
|
-
var _this$fireAnalyticsEv11;
|
|
555
|
-
(_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, deleteSuccessPayload(resourceId, sourceProduct));
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
540
|
const now = Date.now();
|
|
559
541
|
const lastEmittedAt = this.recentDeleteEmissions.get(resourceId);
|
|
560
542
|
if (lastEmittedAt !== undefined && now - lastEmittedAt < DELETE_DEDUPE_WINDOW_MS) {
|
|
@@ -567,7 +549,7 @@ export class SourceSyncBlockStoreManager {
|
|
|
567
549
|
deletionReason: reason,
|
|
568
550
|
mechanism
|
|
569
551
|
};
|
|
570
|
-
(_this$
|
|
552
|
+
(_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, deleteSuccessPayload(resourceId, sourceProduct, enrichment));
|
|
571
553
|
}
|
|
572
554
|
async delete(syncBlockIds, onDelete, onDeleteCompleted, reason, mechanism) {
|
|
573
555
|
try {
|
|
@@ -603,13 +585,12 @@ export class SourceSyncBlockStoreManager {
|
|
|
603
585
|
this.setPendingDeletion(Ids, false);
|
|
604
586
|
};
|
|
605
587
|
(_this$deleteExperienc3 = this.deleteExperience) === null || _this$deleteExperienc3 === void 0 ? void 0 : _this$deleteExperienc3.failure();
|
|
606
|
-
const attributionEnabled = fg('platform_editor_blocks_patch_3');
|
|
607
588
|
results.forEach(result => {
|
|
608
589
|
if (result.success) {
|
|
609
590
|
this.emitDeleteSuccess(result.resourceId, reason, mechanism);
|
|
610
591
|
} else {
|
|
611
|
-
var _this$
|
|
612
|
-
(_this$
|
|
592
|
+
var _this$fireAnalyticsEv12;
|
|
593
|
+
(_this$fireAnalyticsEv12 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv12 === void 0 ? void 0 : _this$fireAnalyticsEv12.call(this, deleteErrorPayload(result.error || 'Failed to delete synced block', result.resourceId, getSourceProductFromResourceIdSafe(result.resourceId), buildErrorAttribution(result.error, result.statusCode)));
|
|
613
594
|
}
|
|
614
595
|
});
|
|
615
596
|
}
|
|
@@ -617,12 +598,12 @@ export class SourceSyncBlockStoreManager {
|
|
|
617
598
|
return isDeleteSuccessful;
|
|
618
599
|
} catch (error) {
|
|
619
600
|
// Thrown (non-result) failure — no structured SyncBlockError/status is available,
|
|
620
|
-
// so the attribution `reason` falls back to `unknown
|
|
621
|
-
const attribution = buildErrorAttribution(
|
|
601
|
+
// so the attribution `reason` falls back to `unknown`.
|
|
602
|
+
const attribution = buildErrorAttribution();
|
|
622
603
|
syncBlockIds.forEach(Ids => {
|
|
623
|
-
var _this$
|
|
604
|
+
var _this$fireAnalyticsEv13;
|
|
624
605
|
this.setPendingDeletion(Ids, false);
|
|
625
|
-
(_this$
|
|
606
|
+
(_this$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, deleteErrorPayload(error.message, Ids.resourceId, getSourceProductFromResourceIdSafe(Ids.resourceId), attribution));
|
|
626
607
|
});
|
|
627
608
|
logException(error, {
|
|
628
609
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
@@ -782,11 +763,11 @@ export class SourceSyncBlockStoreManager {
|
|
|
782
763
|
return sourceInfo;
|
|
783
764
|
});
|
|
784
765
|
} catch (error) {
|
|
785
|
-
var _this$
|
|
766
|
+
var _this$fireAnalyticsEv14;
|
|
786
767
|
logException(error, {
|
|
787
768
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
788
769
|
});
|
|
789
|
-
(_this$
|
|
770
|
+
(_this$fireAnalyticsEv14 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv14 === void 0 ? void 0 : _this$fireAnalyticsEv14.call(this, getSourceInfoErrorPayload(error.message));
|
|
790
771
|
return Promise.resolve(undefined);
|
|
791
772
|
}
|
|
792
773
|
}
|
|
@@ -797,11 +778,11 @@ export class SourceSyncBlockStoreManager {
|
|
|
797
778
|
}
|
|
798
779
|
return this.dataProvider.fetchReferences(resourceId, true);
|
|
799
780
|
} catch (error) {
|
|
800
|
-
var _this$
|
|
781
|
+
var _this$fireAnalyticsEv15;
|
|
801
782
|
logException(error, {
|
|
802
783
|
location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
|
|
803
784
|
});
|
|
804
|
-
(_this$
|
|
785
|
+
(_this$fireAnalyticsEv15 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv15 === void 0 ? void 0 : _this$fireAnalyticsEv15.call(this, fetchReferencesErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
805
786
|
return Promise.resolve({
|
|
806
787
|
error: SyncBlockError.Errored
|
|
807
788
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import rafSchedule from 'raf-schd';
|
|
3
3
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
4
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
4
|
import { isProviderNotReadyError } from '../common/types';
|
|
6
5
|
import { buildFetchErrorAttribution, fetchErrorPayload } from '../utils/errorHandling';
|
|
7
6
|
import { createSyncBlockNode, getSourceProductFromResourceIdSafe } from '../utils/utils';
|
|
@@ -25,14 +24,9 @@ export class SyncBlockBatchFetcher {
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
// EDITOR-7860: not ready — skip and leave resourceIds queued for the
|
|
28
|
-
// next batch once the provider resolves.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// exposure is still tracked — satisfies @atlaskit/platform/no-preconditioning).
|
|
32
|
-
if (fg('platform_editor_blocks_patch_3')) {
|
|
33
|
-
if (this.deps.isProviderReady && !this.deps.isProviderReady()) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
27
|
+
// next batch once the provider resolves.
|
|
28
|
+
if (this.deps.isProviderReady && !this.deps.isProviderReady()) {
|
|
29
|
+
return;
|
|
36
30
|
}
|
|
37
31
|
const resourceIds = Array.from(this.pendingFetchRequests);
|
|
38
32
|
const syncBlockNodes = resourceIds.map(resId => {
|
|
@@ -49,8 +43,8 @@ export class SyncBlockBatchFetcher {
|
|
|
49
43
|
// nothing (no analytics, no exception-tracker noise). Checked before
|
|
50
44
|
// `logException` so the benign case stays silent. Re-schedule so the
|
|
51
45
|
// re-queued IDs are retried on the next frame even if no further
|
|
52
|
-
// `queueFetch()` arrives.
|
|
53
|
-
if (isProviderNotReadyError(error)
|
|
46
|
+
// `queueFetch()` arrives.
|
|
47
|
+
if (isProviderNotReadyError(error)) {
|
|
54
48
|
resourceIds.forEach(resId => this.pendingFetchRequests.add(resId));
|
|
55
49
|
if (!this.isDestroyed) {
|
|
56
50
|
this.scheduledBatchFetch();
|
|
@@ -60,7 +54,7 @@ export class SyncBlockBatchFetcher {
|
|
|
60
54
|
logException(error, {
|
|
61
55
|
location: 'editor-synced-block-provider/syncBlockBatchFetcher/batchedFetchSyncBlocks'
|
|
62
56
|
});
|
|
63
|
-
const attribution = buildFetchErrorAttribution(
|
|
57
|
+
const attribution = buildFetchErrorAttribution(error.message);
|
|
64
58
|
resourceIds.forEach(resId => {
|
|
65
59
|
var _this$deps$getFireAna;
|
|
66
60
|
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message, resId, getSourceProductFromResourceIdSafe(resId), attribution));
|
|
@@ -23,7 +23,7 @@ export class SyncBlockProviderFactoryManager {
|
|
|
23
23
|
logException(error, {
|
|
24
24
|
location: 'editor-synced-block-provider/syncBlockProviderFactoryManager'
|
|
25
25
|
});
|
|
26
|
-
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(
|
|
26
|
+
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(error.message)));
|
|
27
27
|
return undefined;
|
|
28
28
|
}
|
|
29
29
|
let providerFactory = this.providerFactories.get(resourceId);
|
|
@@ -97,7 +97,7 @@ export class SyncBlockProviderFactoryManager {
|
|
|
97
97
|
logException(error, {
|
|
98
98
|
location: 'editor-synced-block-provider/syncBlockProviderFactoryManager'
|
|
99
99
|
});
|
|
100
|
-
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(
|
|
100
|
+
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(error.message)));
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
getSSRProviders(resourceId) {
|
|
@@ -173,7 +173,7 @@ export class SyncBlockProviderFactoryManager {
|
|
|
173
173
|
if (!syncBlock.data.sourceAri || !syncBlock.data.product) {
|
|
174
174
|
var _this$deps$getFireAna3, _syncBlock$data$produ;
|
|
175
175
|
(_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 ? void 0 : _this$deps$getFireAna3(fetchErrorPayload('Sync block source ari or product not found', resourceId, // Prefer cached product when available; fall back to parsing resourceId.
|
|
176
|
-
(_syncBlock$data$produ = syncBlock.data.product) !== null && _syncBlock$data$produ !== void 0 ? _syncBlock$data$produ : getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(
|
|
176
|
+
(_syncBlock$data$produ = syncBlock.data.product) !== null && _syncBlock$data$produ !== void 0 ? _syncBlock$data$produ : getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution('Sync block source ari or product not found')));
|
|
177
177
|
return;
|
|
178
178
|
}
|
|
179
179
|
const parentInfo = dataProvider.retrieveSyncBlockParentInfo(syncBlock.data.sourceAri, syncBlock.data.product);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
3
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
3
|
import { getProductFromSourceAri } from '../clients/block-service/ari';
|
|
5
4
|
import { SyncBlockError } from '../common/types';
|
|
6
5
|
import { fetchReferencesErrorPayload } from '../utils/errorHandling';
|
|
@@ -209,7 +208,6 @@ export const useMemoizedSyncBlockStoreManager = (dataProvider, fireAnalyticsEven
|
|
|
209
208
|
syncBlockStoreManager.setFireAnalyticsEvent(fireAnalyticsEvent);
|
|
210
209
|
}
|
|
211
210
|
|
|
212
|
-
// Gated by platform_synced_block_patch_14:
|
|
213
211
|
// Destroy the SyncBlockStoreManager when:
|
|
214
212
|
// (a) the component unmounts — manager is fully cleaned up, or
|
|
215
213
|
// (b) dataProvider changes — the old manager (now orphaned by the
|
|
@@ -221,9 +219,7 @@ export const useMemoizedSyncBlockStoreManager = (dataProvider, fireAnalyticsEven
|
|
|
221
219
|
// changes, triggering the cleanup for the old instance.
|
|
222
220
|
useEffect(() => {
|
|
223
221
|
return () => {
|
|
224
|
-
|
|
225
|
-
syncBlockStoreManager.destroy();
|
|
226
|
-
}
|
|
222
|
+
syncBlockStoreManager.destroy();
|
|
227
223
|
};
|
|
228
224
|
}, [syncBlockStoreManager]);
|
|
229
225
|
return syncBlockStoreManager;
|
|
@@ -2,7 +2,6 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
import { bind } from 'bind-event-listener';
|
|
3
3
|
import { getDocument } from '@atlaskit/browser-apis';
|
|
4
4
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
5
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
5
|
import { buildFetchErrorAttribution, fetchErrorPayload, fetchSuccessPayload } from '../utils/errorHandling';
|
|
7
6
|
import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
|
|
8
7
|
import { getSourceProductFromResourceIdSafe } from '../utils/utils';
|
|
@@ -17,19 +16,15 @@ export class SyncBlockSubscriptionManager {
|
|
|
17
16
|
// EDITOR-7861: higher ceiling lets transient WS-gateway drops self-heal
|
|
18
17
|
// before a terminal failure is surfaced.
|
|
19
18
|
getMaxRetryAttempts() {
|
|
20
|
-
return
|
|
19
|
+
return SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS_HARDENED;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
// Backoff delay for the given attempt
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// jitter
|
|
27
|
-
// reconnects while guaranteeing a non-zero delay (full jitter could hit 0).
|
|
22
|
+
// Backoff delay for the given attempt (EDITOR-7861): exponential capped at
|
|
23
|
+
// MAX_RETRY_DELAY_MS with equal jitter (capped/2 + random*capped/2) —
|
|
24
|
+
// de-synchronises simultaneous reconnects while guaranteeing a non-zero delay
|
|
25
|
+
// (full jitter could hit 0).
|
|
28
26
|
getReconnectionDelay(attempts) {
|
|
29
27
|
const exponential = SyncBlockSubscriptionManager.INITIAL_RETRY_DELAY_MS * Math.pow(SyncBlockSubscriptionManager.RETRY_BACKOFF_MULTIPLIER, attempts);
|
|
30
|
-
if (!fg('platform_editor_blocks_patch_3')) {
|
|
31
|
-
return exponential;
|
|
32
|
-
}
|
|
33
28
|
const half = Math.min(exponential, SyncBlockSubscriptionManager.MAX_RETRY_DELAY_MS) / 2;
|
|
34
29
|
return Math.round(half + Math.random() * half);
|
|
35
30
|
}
|
|
@@ -39,12 +34,7 @@ export class SyncBlockSubscriptionManager {
|
|
|
39
34
|
_defineProperty(this, "graphqlSubscriptions", new Map());
|
|
40
35
|
_defineProperty(this, "subscriptionChangeListeners", new Set());
|
|
41
36
|
_defineProperty(this, "useRealTimeSubscriptions", false);
|
|
42
|
-
//
|
|
43
|
-
// When a block is moved, the old component unmounts before the new one mounts,
|
|
44
|
-
// causing the cache to be deleted prematurely. We delay deletion to allow
|
|
45
|
-
// the new component to subscribe and cancel the pending deletion.
|
|
46
|
-
_defineProperty(this, "pendingCacheDeletions", new Map());
|
|
47
|
-
// backoff cap (gate ON)
|
|
37
|
+
// backoff cap
|
|
48
38
|
_defineProperty(this, "retryAttempts", new Map());
|
|
49
39
|
_defineProperty(this, "pendingRetries", new Map());
|
|
50
40
|
// Resources whose reconnection exhausted while the tab was hidden: parked here and
|
|
@@ -105,7 +95,7 @@ export class SyncBlockSubscriptionManager {
|
|
|
105
95
|
logException(error, {
|
|
106
96
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/notifySubscriptionChangeListeners'
|
|
107
97
|
});
|
|
108
|
-
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message, undefined, undefined, buildFetchErrorAttribution(
|
|
98
|
+
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message, undefined, undefined, buildFetchErrorAttribution(error.message)));
|
|
109
99
|
}
|
|
110
100
|
});
|
|
111
101
|
}
|
|
@@ -125,16 +115,7 @@ export class SyncBlockSubscriptionManager {
|
|
|
125
115
|
// This handles the case where a block is moved - the old component unmounts
|
|
126
116
|
// (scheduling deletion) but the new component mounts and subscribes before
|
|
127
117
|
// the deletion timeout fires.
|
|
128
|
-
|
|
129
|
-
// Under the flag, cache deletion is owned by the store manager.
|
|
130
|
-
// With the flag off, the legacy 1s timer path is preserved.
|
|
131
|
-
const pendingDeletion = this.pendingCacheDeletions.get(resourceId);
|
|
132
|
-
if (fg('platform_synced_block_patch_14')) {
|
|
133
|
-
this.deps.cancelPendingCacheDeletion(resourceId);
|
|
134
|
-
} else if (pendingDeletion) {
|
|
135
|
-
clearTimeout(pendingDeletion);
|
|
136
|
-
this.pendingCacheDeletions.delete(resourceId);
|
|
137
|
-
}
|
|
118
|
+
this.deps.cancelPendingCacheDeletion(resourceId);
|
|
138
119
|
|
|
139
120
|
// add to subscriptions map
|
|
140
121
|
const resourceSubscriptions = this.subscriptions.get(resourceId) || {};
|
|
@@ -178,30 +159,9 @@ export class SyncBlockSubscriptionManager {
|
|
|
178
159
|
// Notify listeners that subscription was removed
|
|
179
160
|
this.notifySubscriptionChangeListeners();
|
|
180
161
|
|
|
181
|
-
//
|
|
162
|
+
// Delegate cache deletion to the store manager
|
|
182
163
|
// which uses a 30s grace period with guard re-checks.
|
|
183
|
-
|
|
184
|
-
this.deps.scheduleCacheDeletion(resourceId);
|
|
185
|
-
} else {
|
|
186
|
-
// Legacy path (unchanged): delay cache deletion to handle
|
|
187
|
-
// block moves (unmount/remount). When a block is moved, the
|
|
188
|
-
// old component unmounts before the new one mounts. By
|
|
189
|
-
// delaying deletion, we give the new component time to
|
|
190
|
-
// subscribe and cancel this pending deletion, preserving
|
|
191
|
-
// the cached data.
|
|
192
|
-
// TODO: EDITOR-4152 - Rework this logic (superseded by
|
|
193
|
-
// `platform_synced_block_patch_14`).
|
|
194
|
-
const deletionTimeout = setTimeout(() => {
|
|
195
|
-
const hasSubscribers = this.subscriptions.has(resourceId);
|
|
196
|
-
|
|
197
|
-
// Only delete if still no subscribers (wasn't re-subscribed)
|
|
198
|
-
if (!hasSubscribers) {
|
|
199
|
-
this.deps.deleteFromCache(resourceId);
|
|
200
|
-
}
|
|
201
|
-
this.pendingCacheDeletions.delete(resourceId);
|
|
202
|
-
}, 1000);
|
|
203
|
-
this.pendingCacheDeletions.set(resourceId, deletionTimeout);
|
|
204
|
-
}
|
|
164
|
+
this.deps.scheduleCacheDeletion(resourceId);
|
|
205
165
|
} else {
|
|
206
166
|
this.subscriptions.set(resourceId, resourceSubscriptions);
|
|
207
167
|
}
|
|
@@ -278,17 +238,10 @@ export class SyncBlockSubscriptionManager {
|
|
|
278
238
|
logException(error, {
|
|
279
239
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/graphql-subscription'
|
|
280
240
|
});
|
|
281
|
-
// EDITOR-7861: a single socket drop is usually transient and
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
// This branch only runs when the gate is OFF, so buildFetchErrorAttribution
|
|
286
|
-
// would return undefined; the structured attribution (EDITOR-7862) is therefore
|
|
287
|
-
// applied at the gate-ON exhaustion site in scheduleReconnection instead.
|
|
288
|
-
if (!fg('platform_editor_blocks_patch_3')) {
|
|
289
|
-
var _this$deps$getFireAna2;
|
|
290
|
-
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
291
|
-
}
|
|
241
|
+
// EDITOR-7861: a single socket drop is usually transient and recovers
|
|
242
|
+
// on reconnect, so we don't fire a user-facing error here — it's only
|
|
243
|
+
// surfaced on exhaustion, where the structured attribution
|
|
244
|
+
// (EDITOR-7862) is applied too. See scheduleReconnection.
|
|
292
245
|
this.handleSubscriptionTerminated(resourceId);
|
|
293
246
|
}, () => {
|
|
294
247
|
this.handleSubscriptionTerminated(resourceId);
|
|
@@ -324,26 +277,25 @@ export class SyncBlockSubscriptionManager {
|
|
|
324
277
|
const attempts = (_this$retryAttempts$g = this.retryAttempts.get(resourceId)) !== null && _this$retryAttempts$g !== void 0 ? _this$retryAttempts$g : 0;
|
|
325
278
|
const maxAttempts = this.getMaxRetryAttempts();
|
|
326
279
|
if (attempts >= maxAttempts) {
|
|
327
|
-
var _this$deps$
|
|
280
|
+
var _this$deps$getFireAna3;
|
|
328
281
|
// Exhausted all attempts — the only place a WS drop surfaces as a
|
|
329
|
-
// fetch error
|
|
282
|
+
// fetch error (EDITOR-7861).
|
|
330
283
|
const errorMessage = `Subscription reconnection failed after ${attempts} attempts`;
|
|
331
284
|
|
|
332
285
|
// Tab hidden at exhaustion: don't surface a terminal failure (user isn't
|
|
333
286
|
// looking, and most exhaustions self-recover once foregrounded). Park + re-arm
|
|
334
287
|
// on wake, emitting a benign `deferred` signal so suppression stays auditable.
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
var _this$deps$getFireAna3;
|
|
288
|
+
if (this.isDocumentHidden()) {
|
|
289
|
+
var _this$deps$getFireAna2;
|
|
338
290
|
this.deferredExhausted.add(resourceId);
|
|
339
291
|
this.registerWakeListeners();
|
|
340
|
-
(_this$deps$
|
|
292
|
+
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(errorMessage, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(errorMessage, undefined, /* deferred */true)));
|
|
341
293
|
return;
|
|
342
294
|
}
|
|
343
295
|
logException(new Error(errorMessage), {
|
|
344
296
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/max-retries-exhausted'
|
|
345
297
|
});
|
|
346
|
-
(_this$deps$
|
|
298
|
+
(_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 ? void 0 : _this$deps$getFireAna3(fetchErrorPayload(errorMessage, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(errorMessage)));
|
|
347
299
|
return;
|
|
348
300
|
}
|
|
349
301
|
const delay = this.getReconnectionDelay(attempts);
|
|
@@ -502,12 +454,6 @@ export class SyncBlockSubscriptionManager {
|
|
|
502
454
|
this.titleSubscriptions.clear();
|
|
503
455
|
this.subscriptionChangeListeners.clear();
|
|
504
456
|
this.useRealTimeSubscriptions = false;
|
|
505
|
-
|
|
506
|
-
// Clear any pending cache deletions
|
|
507
|
-
for (const timeout of this.pendingCacheDeletions.values()) {
|
|
508
|
-
clearTimeout(timeout);
|
|
509
|
-
}
|
|
510
|
-
this.pendingCacheDeletions.clear();
|
|
511
457
|
}
|
|
512
458
|
shouldUseRealTime() {
|
|
513
459
|
return this.useRealTimeSubscriptions;
|
|
@@ -531,28 +477,26 @@ export class SyncBlockSubscriptionManager {
|
|
|
531
477
|
const callbacks = this.subscriptions.get(syncBlockInstance.resourceId);
|
|
532
478
|
const localIds = callbacks ? Object.keys(callbacks) : [];
|
|
533
479
|
localIds.forEach(localId => {
|
|
534
|
-
var _this$deps$
|
|
535
|
-
(_this$deps$
|
|
480
|
+
var _this$deps$getFireAna4, _syncBlockInstance$da, _syncBlockInstance$da2;
|
|
481
|
+
(_this$deps$getFireAna4 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna4 === void 0 ? void 0 : _this$deps$getFireAna4(fetchSuccessPayload(syncBlockInstance.resourceId, localId, (_syncBlockInstance$da = (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product) !== null && _syncBlockInstance$da !== void 0 ? _syncBlockInstance$da : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId)));
|
|
536
482
|
});
|
|
537
483
|
this.deps.fetchSyncBlockSourceInfo(resolved.resourceId);
|
|
538
484
|
} else {
|
|
539
|
-
var _syncBlockInstance$er, _syncBlockInstance$er2, _this$deps$
|
|
485
|
+
var _syncBlockInstance$er, _syncBlockInstance$er2, _this$deps$getFireAna5, _syncBlockInstance$da3, _syncBlockInstance$da4, _syncBlockInstance$er3, _syncBlockInstance$er4, _syncBlockInstance$er5;
|
|
540
486
|
const errorMessage = ((_syncBlockInstance$er = syncBlockInstance.error) === null || _syncBlockInstance$er === void 0 ? void 0 : _syncBlockInstance$er.reason) || ((_syncBlockInstance$er2 = syncBlockInstance.error) === null || _syncBlockInstance$er2 === void 0 ? void 0 : _syncBlockInstance$er2.type);
|
|
541
487
|
|
|
542
488
|
// Prefer the structured `type` (a `SyncBlockError` enum value) for classification
|
|
543
489
|
// and fall back to the free-text `reason` so source-state/permission strings are
|
|
544
490
|
// still bucketed (EDITOR-7862). The emitted free-text `error` attribute is unchanged.
|
|
545
|
-
(_this$deps$
|
|
491
|
+
(_this$deps$getFireAna5 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna5 === void 0 ? void 0 : _this$deps$getFireAna5(fetchErrorPayload(errorMessage, syncBlockInstance.resourceId, (_syncBlockInstance$da3 = (_syncBlockInstance$da4 = syncBlockInstance.data) === null || _syncBlockInstance$da4 === void 0 ? void 0 : _syncBlockInstance$da4.product) !== null && _syncBlockInstance$da3 !== void 0 ? _syncBlockInstance$da3 : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId), buildFetchErrorAttribution(((_syncBlockInstance$er3 = syncBlockInstance.error) === null || _syncBlockInstance$er3 === void 0 ? void 0 : _syncBlockInstance$er3.type) || ((_syncBlockInstance$er4 = syncBlockInstance.error) === null || _syncBlockInstance$er4 === void 0 ? void 0 : _syncBlockInstance$er4.reason), (_syncBlockInstance$er5 = syncBlockInstance.error) === null || _syncBlockInstance$er5 === void 0 ? void 0 : _syncBlockInstance$er5.statusCode)));
|
|
546
492
|
}
|
|
547
493
|
}
|
|
548
494
|
}
|
|
549
495
|
// Reconnection with exponential backoff.
|
|
550
496
|
_defineProperty(SyncBlockSubscriptionManager, "INITIAL_RETRY_DELAY_MS", 1000);
|
|
551
497
|
_defineProperty(SyncBlockSubscriptionManager, "RETRY_BACKOFF_MULTIPLIER", 2);
|
|
552
|
-
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
553
|
-
// legacy (gate OFF)
|
|
554
498
|
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS_HARDENED", 8);
|
|
555
|
-
//
|
|
499
|
+
// EDITOR-7861
|
|
556
500
|
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_DELAY_MS", 30000);
|
|
557
501
|
// Coalesce wake-event bursts into one re-arm sweep to avoid a reconnection storm.
|
|
558
502
|
_defineProperty(SyncBlockSubscriptionManager, "WAKE_DEBOUNCE_MS", 1000);
|
|
@@ -60,17 +60,9 @@ export const classifyErrorReason = error => {
|
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
62
|
* Builds the {@link ErrorAttributionAttributes} for a failed synced-block operation from
|
|
63
|
-
* the raw result `error` field and optional backend `statusCode
|
|
64
|
-
* when the `platform_editor_blocks_patch_3` gate is OFF, so the new `reason`/`statusCode`
|
|
65
|
-
* attributes are only emitted once the gate is rolled out (EDITOR-7796).
|
|
66
|
-
*
|
|
67
|
-
* `gateEnabled` is injected by the caller (the store managers evaluate `fg(...)`) so this
|
|
68
|
-
* helper stays pure and trivially unit-testable for both gate states.
|
|
63
|
+
* the raw result `error` field and optional backend `statusCode` (EDITOR-7796).
|
|
69
64
|
*/
|
|
70
|
-
export const buildErrorAttribution = (
|
|
71
|
-
if (!gateEnabled) {
|
|
72
|
-
return undefined;
|
|
73
|
-
}
|
|
65
|
+
export const buildErrorAttribution = (error, statusCode) => {
|
|
74
66
|
return {
|
|
75
67
|
reason: classifyErrorReason(error),
|
|
76
68
|
...(statusCode !== undefined && {
|
|
@@ -181,17 +173,10 @@ export const classifyFetchErrorReason = error => {
|
|
|
181
173
|
/**
|
|
182
174
|
* Builds the {@link FetchErrorAttributionAttributes} for a failed fetch/subscribe
|
|
183
175
|
* synced-block operation from the raw `error` field and optional backend `statusCode`.
|
|
184
|
-
*
|
|
185
|
-
* `
|
|
186
|
-
* (EDITOR-7862). The existing free-text `error` attribute is always left unchanged.
|
|
187
|
-
*
|
|
188
|
-
* `gateEnabled` is injected by the caller (the store managers evaluate `fg(...)`) so this
|
|
189
|
-
* helper stays pure and trivially unit-testable for both gate states.
|
|
176
|
+
* Emits the `reason`/`statusCode`/`benign` attributes (EDITOR-7862). The existing
|
|
177
|
+
* free-text `error` attribute is always left unchanged.
|
|
190
178
|
*/
|
|
191
|
-
export const buildFetchErrorAttribution = (
|
|
192
|
-
if (!gateEnabled) {
|
|
193
|
-
return undefined;
|
|
194
|
-
}
|
|
179
|
+
export const buildFetchErrorAttribution = (error, statusCode, deferred) => {
|
|
195
180
|
const reason = classifyFetchErrorReason(error);
|
|
196
181
|
return {
|
|
197
182
|
reason,
|
|
@@ -261,8 +246,8 @@ export function getErrorPayload(actionSubjectId, error, resourceId, sourceProduc
|
|
|
261
246
|
}
|
|
262
247
|
export const fetchErrorPayload = (error, resourceId, sourceProduct, attribution) =>
|
|
263
248
|
// Branch on attribution presence so each call resolves to a concrete overload: with
|
|
264
|
-
// attribution it hits the fetch overload (wider `reason`); without it
|
|
265
|
-
//
|
|
249
|
+
// attribution it hits the fetch overload (wider `reason`); without it, the
|
|
250
|
+
// no-attribution overload. Both produce a fetch event regardless.
|
|
266
251
|
attribution ? getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_FETCH, error, resourceId, sourceProduct, attribution) : getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_FETCH, error, resourceId, sourceProduct);
|
|
267
252
|
export const getSourceInfoErrorPayload = (error, resourceId, sourceProduct) => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_GET_SOURCE_INFO, error, resourceId, sourceProduct);
|
|
268
253
|
export const updateErrorPayload = (error, resourceId, sourceProduct, attribution) => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_UPDATE, error, resourceId, sourceProduct, attribution);
|
|
@@ -272,8 +257,7 @@ export const deleteErrorPayload = (error, resourceId, sourceProduct, attribution
|
|
|
272
257
|
export const updateCacheErrorPayload = (error, resourceId, sourceProduct) => getErrorPayload(ACTION_SUBJECT_ID.SYNCED_BLOCK_UPDATE_CACHE, error, resourceId, sourceProduct);
|
|
273
258
|
/**
|
|
274
259
|
* Payload for `SYNCED_BLOCK_SOURCE_INFO_ORPHANED`. Fired when source-info
|
|
275
|
-
* resolves into a cache that has already been deleted — should be unreachable
|
|
276
|
-
* under `platform_synced_block_patch_14`.
|
|
260
|
+
* resolves into a cache that has already been deleted — should be unreachable.
|
|
277
261
|
*/
|
|
278
262
|
export const sourceInfoOrphanedPayload = (resourceId, sourceProduct, context) => ({
|
|
279
263
|
action: ACTION.ERROR,
|
|
@@ -349,14 +333,13 @@ export const createSuccessPayload = (resourceId, sourceProduct) => {
|
|
|
349
333
|
|
|
350
334
|
/**
|
|
351
335
|
* Optional enrichment for the `syncedBlockCreate` success event. All fields
|
|
352
|
-
* optional so
|
|
336
|
+
* optional so legacy payloads are unchanged. `inputMethod`: creating
|
|
353
337
|
* surface (enum, PII-safe). `createdEmpty`: true from an empty selection, false
|
|
354
338
|
* when content was converted.
|
|
355
339
|
*/
|
|
356
340
|
|
|
357
341
|
/**
|
|
358
|
-
* Operational `syncedBlockCreate` success event,
|
|
359
|
-
* `platform_editor_blocks_patch_4`, with the `blockInstanceId` join key and,
|
|
342
|
+
* Operational `syncedBlockCreate` success event with the `blockInstanceId` join key and,
|
|
360
343
|
* when available, the `inputMethod` + `createdEmpty` creation-type signals.
|
|
361
344
|
*/
|
|
362
345
|
export const createSuccessOperationalPayload = (resourceId, blockInstanceId, sourceProduct, enrichment) => ({
|
|
@@ -382,8 +365,7 @@ export const createSuccessOperationalPayload = (resourceId, blockInstanceId, sou
|
|
|
382
365
|
});
|
|
383
366
|
|
|
384
367
|
/**
|
|
385
|
-
* Operational first-content-added event
|
|
386
|
-
* `platform_editor_blocks_patch_4`. Fired once when a block created empty first
|
|
368
|
+
* Operational first-content-added event. Fired once when a block created empty first
|
|
387
369
|
* gains user content. Join keys only (`resourceId` + `blockInstanceId`), no user
|
|
388
370
|
* content (PII-safe).
|
|
389
371
|
*/
|
|
@@ -419,9 +401,8 @@ export const updateSuccessPayload = (resourceId, hasReference, sourceProduct) =>
|
|
|
419
401
|
});
|
|
420
402
|
|
|
421
403
|
/**
|
|
422
|
-
* Optional enrichment for the `syncedBlockDelete` success event
|
|
423
|
-
*
|
|
424
|
-
* is unchanged; `blockInstanceId` is the bare-uuid join key.
|
|
404
|
+
* Optional enrichment for the `syncedBlockDelete` success event. All fields are
|
|
405
|
+
* optional for extensibility; `blockInstanceId` is the bare-uuid join key.
|
|
425
406
|
*/
|
|
426
407
|
|
|
427
408
|
export const deleteSuccessPayload = (resourceId, sourceProduct, enrichment) => ({
|
package/dist/esm/common/types.js
CHANGED
|
@@ -49,14 +49,13 @@ export var SyncBlockError = /*#__PURE__*/function (SyncBlockError) {
|
|
|
49
49
|
* asynchronously and `destroy()` nulls it on orphaned managers, so queued/
|
|
50
50
|
* in-flight ops throw `Data provider not set` — previously mis-logged as a real
|
|
51
51
|
* error. These let throw and catch sites agree on one non-string-matched signal
|
|
52
|
-
* so the residual false errors are suppressed.
|
|
53
|
-
* `platform_editor_blocks_patch_3`.
|
|
52
|
+
* so the residual false errors are suppressed.
|
|
54
53
|
*
|
|
55
54
|
* NB: these intentionally live here rather than in a dedicated module to avoid
|
|
56
55
|
* adding a downstream file to consuming Jira packages' Thunderstone complexity.
|
|
57
56
|
*/
|
|
58
57
|
|
|
59
|
-
/** Legacy message — kept identical for
|
|
58
|
+
/** Legacy message — kept identical for historical events. */
|
|
60
59
|
export var PROVIDER_NOT_READY_MESSAGE = 'Data provider not set';
|
|
61
60
|
|
|
62
61
|
/**
|