@atlaskit/editor-synced-block-provider 8.6.12 → 8.6.14

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/AGENTS.md CHANGED
@@ -4,7 +4,7 @@
4
4
  >
5
5
  > **For workflow guidance, debugging, and cross-package task guides, load the `synced-blocks`
6
6
  > skill:**
7
- > `get_skill(skill_name_or_path="platform/packages/editor/.rovodev/skills/synced-blocks/SKILL.md")`
7
+ > `get_skill(skill_name_or_path="platform/packages/editor/.agents/skills/synced-blocks/SKILL.md")`
8
8
 
9
9
  ---
10
10
 
@@ -22,10 +22,16 @@ plugin and the renderer across Confluence and Jira.
22
22
  src/
23
23
  ├── index.ts # Barrel export
24
24
  ├── store-manager/
25
- │ ├── syncBlockStoreManager.ts # Parent coordinator for source + reference managers
26
- │ ├── referenceSyncBlockStoreManager.ts # Reference block lifecycle, cache, subscriptions, flush
27
- └── sourceSyncBlockStoreManager.ts # Source block create, update, delete, flush,
28
- hasPendingCreations(), discardUnpublishedBlocks()
25
+ │ ├── syncBlockStoreManager.ts # Facade: delegates to source + reference managers
26
+ │ ├── sourceSyncBlockStoreManager.ts # Source lifecycle: updateSyncBlockData, flush,
27
+ │ hasUnsavedChanges(), hasPendingCreations(),
28
+ │ commitPendingCreation(), discardUnpublishedBlocks(),
29
+ │ │ deleteSyncBlocksWithConfirmation()
30
+ │ ├── referenceSyncBlockStoreManager.ts # Reference lifecycle: fetch, cache, subscriptions, flush
31
+ │ ├── syncBlockBatchFetcher.ts # Debounced/deduped batch fetch of reference data
32
+ │ ├── syncBlockInMemorySessionCache.ts # Session cache (survives view↔edit within a session)
33
+ │ ├── syncBlockSubscriptionManager.ts # Real-time subscription registry (AGG/Relay)
34
+ │ └── syncBlockProviderFactoryManager.ts # Builds/wires the provider instances
29
35
  ├── clients/
30
36
  │ ├── block-service/
31
37
  │ │ ├── blockService.ts # Block service API client (fetch, batch, CRUD)
@@ -43,7 +49,7 @@ src/
43
49
  │ ├── useFetchSyncBlockTitle.ts # React hook: fetch source title/url metadata
44
50
  │ └── useHandleContentChanges.ts # Wires editor content changes into source manager
45
51
  ├── common/
46
- │ ├── consts.ts # Shared constants (debounce timings, etc.)
52
+ │ ├── consts.ts # Shared constants (e.g. SYNC_BLOCK_PRODUCTS)
47
53
  │ ├── rebase-transaction.ts # Shared transaction rebase helpers
48
54
  │ └── types.ts # Cross-module types
49
55
  ├── utils/
@@ -64,19 +70,23 @@ src/
64
70
  ### Store Manager Hierarchy
65
71
 
66
72
  ```
67
- SyncBlockStoreManager (parent coordinator)
68
- ├── SourceSyncBlockStoreManager
69
- │ ├── create(content) → Block Service API returns resourceId
70
- │ ├── updateSyncBlockData(node) → marks isDirty, caches content
71
- │ ├── flush() → persist all dirty changes to backend
72
- │ ├── hasUnsavedChanges() → checks isDirty + hasReceivedContentChange
73
- │ ├── hasPendingCreations() → O(1) pending-creation check (EDITOR-6930)
74
- │ ├── discardUnpublishedBlocks() → delete unpublished blocks (EDITOR-6473)
75
- └── delete(resourceId) → soft delete with confirmation
76
- └── ReferenceSyncBlockStoreManager
73
+ SyncBlockStoreManager (facade — delegates to source + reference managers)
74
+ ├── sourceManager: SourceSyncBlockStoreManager
75
+ │ ├── updateSyncBlockData(node) → marks isDirty + hasReceivedContentChange, caches content
76
+ │ ├── flush() → persist all dirty source changes to Block Service
77
+ │ ├── hasUnsavedChanges() → hasReceivedContentChange && any block isDirty
78
+ │ ├── hasPendingCreations() / isPendingCreation(id) O(1) pending-creation checks (EDITOR-6930)
79
+ │ ├── commitPendingCreation(...) → reconcile a pending source after it persists
80
+ │ ├── createBodiedSyncBlockNode(...) / generateBodiedSyncBlockAttrs() build a new source node
81
+ ├── discardUnpublishedBlocks() → drop never-published sources (EDITOR-6473)
82
+ │ ├── deleteSyncBlocksWithConfirmation() → confirmed source deletion (+ retryDeletion())
83
+ │ ├── registerConfirmationCallback() / setFireAnalyticsEvent() → product-supplied hooks
84
+ │ └── (no create()/delete(): sources are created lazily then flushed — see the skill)
85
+ └── referenceManager: ReferenceSyncBlockStoreManager
77
86
  ├── fetchSyncBlocksData(nodes) → batch fetch with deduplication
78
- ├── subscribeToSyncBlock(resourceId, callback) → AGG WebSocket
87
+ ├── subscribeToSyncBlock(resourceId, callback) → AGG WebSocket / Relay
79
88
  ├── fetchSyncBlockSourceInfo(resourceId) → title, URL metadata
89
+ ├── flush() → flush reference-side pending work
80
90
  └── destroy() → cleanup subscriptions and batchers
81
91
  ```
82
92
 
@@ -92,7 +102,10 @@ SyncBlockStoreManager (parent coordinator)
92
102
  ### Block Service API
93
103
 
94
104
  The client in `clients/block-service/blockService.ts` communicates via GraphQL at
95
- `/gateway/api/graphql`: Fetch, Create, Update (debounced 3s), Delete, Source Info, References Info.
105
+ `/gateway/api/graphql`: Fetch, Create, Update, Delete, Source Info, References Info. The GraphQL
106
+ mutations are **not** debounced at the client — write batching is driven by the product layer
107
+ calling `flush()` (Confluence draft-sync/publish, Jira save). Reference reads are batched/deduped
108
+ via `syncBlockBatchFetcher.ts`. Grep for the current timing constants rather than assuming a value.
96
109
 
97
110
  ### Media Token Fetching
98
111
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/editor-synced-block-provider
2
2
 
3
+ ## 8.6.14
4
+
5
+ ### Patch Changes
6
+
7
+ - [`1207d5bc1e287`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1207d5bc1e287) -
8
+ Show zero synced locations immediately for newly inserted source blocks
9
+ - Updated dependencies
10
+
11
+ ## 8.6.13
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+
3
17
  ## 8.6.12
4
18
 
5
19
  ### Patch Changes
@@ -66,6 +66,13 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
66
66
  * ADF; removed once consumed.
67
67
  */
68
68
  (0, _defineProperty2.default)(this, "creationEnrichment", new Map());
69
+ /**
70
+ * Source blocks created by the local insert command in this editor session that
71
+ * have not yet been reconciled with authoritative reference data. This state is
72
+ * intentionally kept out of ADF and the backend cache so reloaded, restored,
73
+ * copied, and remotely inserted sources cannot inherit it.
74
+ */
75
+ (0, _defineProperty2.default)(this, "newSourceBlockResourceIds", new Set());
69
76
  /**
70
77
  * Resource IDs of blocks created empty this session that have not yet fired
71
78
  * the first-content-added event. Added on empty creation, removed when the
@@ -131,6 +138,16 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
131
138
  value: function isSourceBlock(node) {
132
139
  return node.type.name === 'bodiedSyncBlock';
133
140
  }
141
+ }, {
142
+ key: "isNewSourceBlock",
143
+ value: function isNewSourceBlock(resourceId) {
144
+ return this.newSourceBlockResourceIds.has(resourceId);
145
+ }
146
+ }, {
147
+ key: "clearNewSourceBlock",
148
+ value: function clearNewSourceBlock(resourceId) {
149
+ this.newSourceBlockResourceIds.delete(resourceId);
150
+ }
134
151
 
135
152
  /**
136
153
  * Add/update a sync block node to/from the local cache
@@ -443,6 +460,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
443
460
  var _this$fireAnalyticsEv6;
444
461
  // Delete the node from cache if fail to create so it's not flushed to BE
445
462
  this.syncBlockCache.delete(resourceId || '');
463
+ this.newSourceBlockResourceIds.delete(resourceId || '');
446
464
  // Creation failed, so there is no block to add content to — drop the
447
465
  // first-content tracking entry so a later unrelated edit cannot fire it.
448
466
  this.awaitingFirstContent.delete(resourceId || '');
@@ -541,6 +559,9 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
541
559
  if (!this.dataProvider) {
542
560
  throw new Error('Data provider not set');
543
561
  }
562
+ if (enrichment) {
563
+ this.newSourceBlockResourceIds.add(resourceId);
564
+ }
544
565
 
545
566
  // add the node to the cache
546
567
  this.updateSyncBlockData(node, false);
@@ -586,6 +607,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
586
607
  this.pendingCreationPromises.set(resourceId, creationPromise);
587
608
  } catch (error) {
588
609
  var _this$fireAnalyticsEv8;
610
+ this.newSourceBlockResourceIds.delete(resourceId);
589
611
  if (this.isPendingCreation(resourceId)) {
590
612
  this.commitPendingCreation(false, resourceId);
591
613
  }
@@ -1037,6 +1059,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
1037
1059
  this.pendingCreationPromises.clear();
1038
1060
  this.creationsTimedOutDuringFlush.clear();
1039
1061
  this.creationEnrichment.clear();
1062
+ this.newSourceBlockResourceIds.clear();
1040
1063
  this.awaitingFirstContent.clear();
1041
1064
  this.recentDeleteEmissions.clear();
1042
1065
  this.dataProvider = undefined;
@@ -47,6 +47,13 @@ export class SourceSyncBlockStoreManager {
47
47
  * ADF; removed once consumed.
48
48
  */
49
49
  _defineProperty(this, "creationEnrichment", new Map());
50
+ /**
51
+ * Source blocks created by the local insert command in this editor session that
52
+ * have not yet been reconciled with authoritative reference data. This state is
53
+ * intentionally kept out of ADF and the backend cache so reloaded, restored,
54
+ * copied, and remotely inserted sources cannot inherit it.
55
+ */
56
+ _defineProperty(this, "newSourceBlockResourceIds", new Set());
50
57
  /**
51
58
  * Resource IDs of blocks created empty this session that have not yet fired
52
59
  * the first-content-added event. Added on empty creation, removed when the
@@ -104,6 +111,12 @@ export class SourceSyncBlockStoreManager {
104
111
  isSourceBlock(node) {
105
112
  return node.type.name === 'bodiedSyncBlock';
106
113
  }
114
+ isNewSourceBlock(resourceId) {
115
+ return this.newSourceBlockResourceIds.has(resourceId);
116
+ }
117
+ clearNewSourceBlock(resourceId) {
118
+ this.newSourceBlockResourceIds.delete(resourceId);
119
+ }
107
120
 
108
121
  /**
109
122
  * Add/update a sync block node to/from the local cache
@@ -368,6 +381,7 @@ export class SourceSyncBlockStoreManager {
368
381
  var _this$fireAnalyticsEv8;
369
382
  // Delete the node from cache if fail to create so it's not flushed to BE
370
383
  this.syncBlockCache.delete(resourceId || '');
384
+ this.newSourceBlockResourceIds.delete(resourceId || '');
371
385
  // Creation failed, so there is no block to add content to — drop the
372
386
  // first-content tracking entry so a later unrelated edit cannot fire it.
373
387
  this.awaitingFirstContent.delete(resourceId || '');
@@ -457,6 +471,9 @@ export class SourceSyncBlockStoreManager {
457
471
  if (!this.dataProvider) {
458
472
  throw new Error('Data provider not set');
459
473
  }
474
+ if (enrichment) {
475
+ this.newSourceBlockResourceIds.add(resourceId);
476
+ }
460
477
 
461
478
  // add the node to the cache
462
479
  this.updateSyncBlockData(node, false);
@@ -502,6 +519,7 @@ export class SourceSyncBlockStoreManager {
502
519
  this.pendingCreationPromises.set(resourceId, creationPromise);
503
520
  } catch (error) {
504
521
  var _this$fireAnalyticsEv10;
522
+ this.newSourceBlockResourceIds.delete(resourceId);
505
523
  if (this.isPendingCreation(resourceId)) {
506
524
  this.commitPendingCreation(false, resourceId);
507
525
  }
@@ -799,6 +817,7 @@ export class SourceSyncBlockStoreManager {
799
817
  this.pendingCreationPromises.clear();
800
818
  this.creationsTimedOutDuringFlush.clear();
801
819
  this.creationEnrichment.clear();
820
+ this.newSourceBlockResourceIds.clear();
802
821
  this.awaitingFirstContent.clear();
803
822
  this.recentDeleteEmissions.clear();
804
823
  this.dataProvider = undefined;
@@ -59,6 +59,13 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
59
59
  * ADF; removed once consumed.
60
60
  */
61
61
  _defineProperty(this, "creationEnrichment", new Map());
62
+ /**
63
+ * Source blocks created by the local insert command in this editor session that
64
+ * have not yet been reconciled with authoritative reference data. This state is
65
+ * intentionally kept out of ADF and the backend cache so reloaded, restored,
66
+ * copied, and remotely inserted sources cannot inherit it.
67
+ */
68
+ _defineProperty(this, "newSourceBlockResourceIds", new Set());
62
69
  /**
63
70
  * Resource IDs of blocks created empty this session that have not yet fired
64
71
  * the first-content-added event. Added on empty creation, removed when the
@@ -124,6 +131,16 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
124
131
  value: function isSourceBlock(node) {
125
132
  return node.type.name === 'bodiedSyncBlock';
126
133
  }
134
+ }, {
135
+ key: "isNewSourceBlock",
136
+ value: function isNewSourceBlock(resourceId) {
137
+ return this.newSourceBlockResourceIds.has(resourceId);
138
+ }
139
+ }, {
140
+ key: "clearNewSourceBlock",
141
+ value: function clearNewSourceBlock(resourceId) {
142
+ this.newSourceBlockResourceIds.delete(resourceId);
143
+ }
127
144
 
128
145
  /**
129
146
  * Add/update a sync block node to/from the local cache
@@ -436,6 +453,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
436
453
  var _this$fireAnalyticsEv6;
437
454
  // Delete the node from cache if fail to create so it's not flushed to BE
438
455
  this.syncBlockCache.delete(resourceId || '');
456
+ this.newSourceBlockResourceIds.delete(resourceId || '');
439
457
  // Creation failed, so there is no block to add content to — drop the
440
458
  // first-content tracking entry so a later unrelated edit cannot fire it.
441
459
  this.awaitingFirstContent.delete(resourceId || '');
@@ -534,6 +552,9 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
534
552
  if (!this.dataProvider) {
535
553
  throw new Error('Data provider not set');
536
554
  }
555
+ if (enrichment) {
556
+ this.newSourceBlockResourceIds.add(resourceId);
557
+ }
537
558
 
538
559
  // add the node to the cache
539
560
  this.updateSyncBlockData(node, false);
@@ -579,6 +600,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
579
600
  this.pendingCreationPromises.set(resourceId, creationPromise);
580
601
  } catch (error) {
581
602
  var _this$fireAnalyticsEv8;
603
+ this.newSourceBlockResourceIds.delete(resourceId);
582
604
  if (this.isPendingCreation(resourceId)) {
583
605
  this.commitPendingCreation(false, resourceId);
584
606
  }
@@ -1030,6 +1052,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
1030
1052
  this.pendingCreationPromises.clear();
1031
1053
  this.creationsTimedOutDuringFlush.clear();
1032
1054
  this.creationEnrichment.clear();
1055
+ this.newSourceBlockResourceIds.clear();
1033
1056
  this.awaitingFirstContent.clear();
1034
1057
  this.recentDeleteEmissions.clear();
1035
1058
  this.dataProvider = undefined;
@@ -1 +1 @@
1
- export declare const SYNC_BLOCK_PRODUCTS: readonly ["confluence-page", "jira-work-item"];
1
+ export declare const SYNC_BLOCK_PRODUCTS: readonly ['confluence-page', 'jira-work-item'];
@@ -43,6 +43,13 @@ export declare class SourceSyncBlockStoreManager {
43
43
  * ADF; removed once consumed.
44
44
  */
45
45
  private creationEnrichment;
46
+ /**
47
+ * Source blocks created by the local insert command in this editor session that
48
+ * have not yet been reconciled with authoritative reference data. This state is
49
+ * intentionally kept out of ADF and the backend cache so reloaded, restored,
50
+ * copied, and remotely inserted sources cannot inherit it.
51
+ */
52
+ private newSourceBlockResourceIds;
46
53
  /**
47
54
  * Resource IDs of blocks created empty this session that have not yet fired
48
55
  * the first-content-added event. Added on empty creation, removed when the
@@ -76,6 +83,8 @@ export declare class SourceSyncBlockStoreManager {
76
83
  registerPostCreationFlushCallback(callback: () => void): void;
77
84
  setFireAnalyticsEvent(fireAnalyticsEvent?: (payload: SyncBlockEventPayload) => void): void;
78
85
  isSourceBlock(node: PMNode): boolean;
86
+ isNewSourceBlock(resourceId: ResourceId): boolean;
87
+ clearNewSourceBlock(resourceId: ResourceId): void;
79
88
  /**
80
89
  * Add/update a sync block node to/from the local cache
81
90
  * @param syncBlockNode - The sync block node to update
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  "@atlaskit/editor-prosemirror": "^8.0.0",
23
23
  "@atlaskit/node-data-provider": "^13.0.0",
24
24
  "@atlaskit/platform-feature-flags": "^2.1.0",
25
- "@atlaskit/tmp-editor-statsig": "^134.0.0",
25
+ "@atlaskit/tmp-editor-statsig": "^135.6.0",
26
26
  "@babel/runtime": "^7.0.0",
27
27
  "@compiled/react": "^1.0.0",
28
28
  "bind-event-listener": "^3.0.0",
@@ -32,7 +32,7 @@
32
32
  "uuid": "^3.1.0"
33
33
  },
34
34
  "peerDependencies": {
35
- "@atlaskit/editor-common": "^116.40.0",
35
+ "@atlaskit/editor-common": "^116.44.0",
36
36
  "react": "^18.2.0"
37
37
  },
38
38
  "devDependencies": {
@@ -76,7 +76,7 @@
76
76
  }
77
77
  },
78
78
  "name": "@atlaskit/editor-synced-block-provider",
79
- "version": "8.6.12",
79
+ "version": "8.6.14",
80
80
  "description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
81
81
  "author": "Atlassian Pty Ltd",
82
82
  "license": "Apache-2.0",