@atlaskit/editor-synced-block-provider 4.3.2 → 4.3.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.
- package/AGENTS.md +33 -73
- package/CHANGELOG.md +9 -0
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +7 -1
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +7 -1
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +7 -1
- package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +3 -1
- package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +3 -1
- package/package.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Synced Block Provider — Developer Agent Guide
|
|
2
2
|
|
|
3
|
-
> **Package**: `@atlaskit/editor-synced-block-provider`
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
3
|
+
> **Package**: `@atlaskit/editor-synced-block-provider`
|
|
4
|
+
>
|
|
5
|
+
> **For workflow guidance, debugging, and cross-package task guides, load the `synced-blocks` skill:**
|
|
6
|
+
> `get_skill(skill_name_or_path="platform/packages/editor/.rovodev/skills/synced-blocks/SKILL.md")`
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -19,29 +19,29 @@ plugin and the renderer across Confluence and Jira.
|
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
src/
|
|
22
|
-
├── index.ts
|
|
22
|
+
├── index.ts # Barrel export
|
|
23
23
|
├── store-manager/
|
|
24
|
-
│ ├── syncBlockStoreManager.ts
|
|
25
|
-
│ ├── referenceSyncBlockStoreManager.ts
|
|
26
|
-
│ └── sourceSyncBlockStoreManager.ts
|
|
24
|
+
│ ├── syncBlockStoreManager.ts # Parent coordinator for source + reference managers
|
|
25
|
+
│ ├── referenceSyncBlockStoreManager.ts # Reference block lifecycle, cache, subscriptions, flush
|
|
26
|
+
│ └── sourceSyncBlockStoreManager.ts # Source block create, update, delete, flush
|
|
27
27
|
├── clients/
|
|
28
28
|
│ ├── block-service/
|
|
29
|
-
│ │ ├── blockService.ts
|
|
30
|
-
│ │ └── ari.ts
|
|
29
|
+
│ │ ├── blockService.ts # Block service API client (fetch, batch, CRUD)
|
|
30
|
+
│ │ └── ari.ts # Block ARI generation/parsing
|
|
31
31
|
│ ├── confluence/
|
|
32
|
-
│ │ ├── ari.ts
|
|
33
|
-
│ │ └── fetchMediaToken.ts
|
|
32
|
+
│ │ ├── ari.ts # Confluence page ARI generation/parsing
|
|
33
|
+
│ │ └── fetchMediaToken.ts # Media token fetching via GraphQL (MediaUploadTokenQuery)
|
|
34
34
|
│ └── jira/
|
|
35
|
-
│ └── ari.ts
|
|
35
|
+
│ └── ari.ts # Jira work item ARI generation/parsing
|
|
36
36
|
├── providers/
|
|
37
37
|
│ └── block-service/
|
|
38
|
-
│ └── blockServiceAPI.ts
|
|
39
|
-
└── types/
|
|
38
|
+
│ └── blockServiceAPI.ts # Provider factory and API helpers
|
|
39
|
+
└── types/ # Shared types
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
## Key
|
|
44
|
+
## Key Exports and Types
|
|
45
45
|
|
|
46
46
|
### Store Manager Hierarchy
|
|
47
47
|
|
|
@@ -49,81 +49,41 @@ src/
|
|
|
49
49
|
SyncBlockStoreManager (parent coordinator)
|
|
50
50
|
├── SourceSyncBlockStoreManager
|
|
51
51
|
│ ├── create(content) → Block Service API → returns resourceId
|
|
52
|
-
│ ├──
|
|
53
|
-
│ ├──
|
|
54
|
-
│
|
|
52
|
+
│ ├── updateSyncBlockData(node) → marks isDirty, caches content
|
|
53
|
+
│ ├── flush() → persist all dirty changes to backend
|
|
54
|
+
│ ├── hasUnsavedChanges() → checks isDirty + hasReceivedContentChange
|
|
55
|
+
│ └── delete(resourceId) → soft delete with confirmation
|
|
55
56
|
└── ReferenceSyncBlockStoreManager
|
|
56
57
|
├── fetchSyncBlocksData(nodes) → batch fetch with deduplication
|
|
57
|
-
├── subscribeToSyncBlock(resourceId,
|
|
58
|
+
├── subscribeToSyncBlock(resourceId, callback) → AGG WebSocket
|
|
58
59
|
├── fetchSyncBlockSourceInfo(resourceId) → title, URL metadata
|
|
59
|
-
├── getFromCache(resourceId) → retrieve cached data
|
|
60
|
-
├── flush() → save reference changes to backend
|
|
61
60
|
└── destroy() → cleanup subscriptions and batchers
|
|
62
61
|
```
|
|
63
62
|
|
|
64
|
-
### ARI
|
|
63
|
+
### ARI Utilities
|
|
65
64
|
|
|
66
|
-
| Function |
|
|
67
|
-
| ------------------------------------------------------------ |
|
|
68
|
-
| `generateBlockAri({cloudId, parentId, product, resourceId})` |
|
|
69
|
-
| `generateBlockAriFromReference({cloudId, resourceId})` |
|
|
70
|
-
| `getConfluencePageAri({pageId, cloudId, pageType})` | Confluence page
|
|
71
|
-
| `getJiraWorkItemAri({cloudId, workItemId})` | Jira issue
|
|
72
|
-
| `getJiraWorkItemIdFromAri(ari)` | Extract issue ID from ARI | — |
|
|
65
|
+
| Function | Purpose |
|
|
66
|
+
| ------------------------------------------------------------ | -------------------------- |
|
|
67
|
+
| `generateBlockAri({cloudId, parentId, product, resourceId})` | Generate source block ARI |
|
|
68
|
+
| `generateBlockAriFromReference({cloudId, resourceId})` | Generate reference ARI |
|
|
69
|
+
| `getConfluencePageAri({pageId, cloudId, pageType})` | Confluence page ARI |
|
|
70
|
+
| `getJiraWorkItemAri({cloudId, workItemId})` | Jira issue ARI |
|
|
73
71
|
|
|
74
72
|
### Block Service API
|
|
75
73
|
|
|
76
74
|
The client in `clients/block-service/blockService.ts` communicates via GraphQL at
|
|
77
|
-
`/gateway/api/graphql`:
|
|
78
|
-
|
|
79
|
-
- **Fetch**: Single or batch block content retrieval
|
|
80
|
-
- **Create**: Register new source block with content
|
|
81
|
-
- **Update**: Push content changes (debounced 3s)
|
|
82
|
-
- **Delete**: Soft delete a source block
|
|
83
|
-
- **Source Info**: Fetch metadata (source page title, URL)
|
|
84
|
-
- **References Info**: Fetch list of locations referencing a block
|
|
75
|
+
`/gateway/api/graphql`: Fetch, Create, Update (debounced 3s), Delete, Source Info, References Info.
|
|
85
76
|
|
|
86
77
|
### Media Token Fetching
|
|
87
78
|
|
|
88
79
|
`fetchMediaToken(contentId)` → GraphQL `MediaUploadTokenQuery` → returns
|
|
89
80
|
`{token, config: {clientId, fileStoreUrl}, collectionId}`
|
|
90
81
|
|
|
91
|
-
Used when synced blocks contain media (images, files) — the reference needs a valid token to render
|
|
92
|
-
media from the source page.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Common Tasks
|
|
97
|
-
|
|
98
|
-
### Adding a new API method
|
|
99
|
-
|
|
100
|
-
1. Add the GraphQL query/mutation in `clients/block-service/blockService.ts`
|
|
101
|
-
2. Expose it through the appropriate store manager
|
|
102
|
-
3. Export from `src/index.ts` if needed by product integrations
|
|
103
|
-
4. Add tests in `editor-synced-block-provider-tests`
|
|
104
|
-
|
|
105
|
-
### Debugging data issues
|
|
106
|
-
|
|
107
|
-
1. Check `ReferenceSyncBlockStoreManager` cache state
|
|
108
|
-
2. Verify ARI format matches expected pattern for the product
|
|
109
|
-
3. Check Block Service API responses in network tab (look for `/gateway/api/graphql`)
|
|
110
|
-
4. Use analytics:
|
|
111
|
-
[HOW-TO: Debug errors](https://hello.atlassian.net/wiki/spaces/egcuc/pages/6342760320)
|
|
112
|
-
|
|
113
|
-
### Adding support for a new product
|
|
114
|
-
|
|
115
|
-
1. Create ARI utilities in `clients/{product}/ari.ts`
|
|
116
|
-
2. Ensure `generateBlockAri` supports the new product type
|
|
117
|
-
3. Add media token fetching if the product has media content
|
|
118
|
-
4. Update store managers if the product has unique lifecycle requirements
|
|
119
|
-
|
|
120
82
|
---
|
|
121
83
|
|
|
122
84
|
## Related Packages
|
|
123
85
|
|
|
124
|
-
- **Plugin**: `platform/packages/editor/editor-plugin-synced-block/`
|
|
125
|
-
- **Renderer**: `platform/packages/editor/editor-synced-block-renderer/`
|
|
126
|
-
- **Confluence**: `confluence/next/packages/fabric-providers/src/SyncedBlockProvider.ts`
|
|
127
|
-
|
|
128
|
-
- **Jira**: `jira/src/packages/issue/issue-view-synced-block-provider/` — wraps this provider with
|
|
129
|
-
Relay
|
|
86
|
+
- **Plugin**: `platform/packages/editor/editor-plugin-synced-block/`
|
|
87
|
+
- **Renderer**: `platform/packages/editor/editor-synced-block-renderer/`
|
|
88
|
+
- **Confluence**: `confluence/next/packages/fabric-providers/src/SyncedBlockProvider.ts`
|
|
89
|
+
- **Jira**: `jira/src/packages/issue/issue-view-synced-block-provider/`
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @atlaskit/editor-synced-block-provider
|
|
2
2
|
|
|
3
|
+
## 4.3.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`15deee785151b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/15deee785151b) -
|
|
8
|
+
EDITOR-6174 Pass node to createBodiedSyncBlockNode to cache content on creation, preventing false
|
|
9
|
+
unsaved changes on page refresh
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
3
12
|
## 4.3.2
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -339,10 +339,12 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
|
|
|
339
339
|
/**
|
|
340
340
|
* Create a bodiedSyncBlock node with empty content to backend
|
|
341
341
|
* @param attrs attributes Ids of the node
|
|
342
|
+
* @param node the ProseMirror node to cache
|
|
343
|
+
* @param onCompletion callback invoked when creation completes
|
|
342
344
|
*/
|
|
343
345
|
}, {
|
|
344
346
|
key: "createBodiedSyncBlockNode",
|
|
345
|
-
value: function createBodiedSyncBlockNode(attrs, onCompletion) {
|
|
347
|
+
value: function createBodiedSyncBlockNode(attrs, node, onCompletion) {
|
|
346
348
|
var _this4 = this;
|
|
347
349
|
if (this.viewMode === 'view' && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_8')) {
|
|
348
350
|
return;
|
|
@@ -354,6 +356,10 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
|
|
|
354
356
|
if (!this.dataProvider) {
|
|
355
357
|
throw new Error('Data provider not set');
|
|
356
358
|
}
|
|
359
|
+
if ((0, _platformFeatureFlags.fg)('platform_synced_block_update_refactor')) {
|
|
360
|
+
// add the node to the cache
|
|
361
|
+
this.updateSyncBlockData(node);
|
|
362
|
+
}
|
|
357
363
|
this.creationCompletionCallbacks.set(resourceId, onCompletion);
|
|
358
364
|
(_this$createExperienc = this.createExperience) === null || _this$createExperienc === void 0 || _this$createExperienc.start({});
|
|
359
365
|
this.dataProvider.createNodeData({
|
|
@@ -269,8 +269,10 @@ export class SourceSyncBlockStoreManager {
|
|
|
269
269
|
/**
|
|
270
270
|
* Create a bodiedSyncBlock node with empty content to backend
|
|
271
271
|
* @param attrs attributes Ids of the node
|
|
272
|
+
* @param node the ProseMirror node to cache
|
|
273
|
+
* @param onCompletion callback invoked when creation completes
|
|
272
274
|
*/
|
|
273
|
-
createBodiedSyncBlockNode(attrs, onCompletion) {
|
|
275
|
+
createBodiedSyncBlockNode(attrs, node, onCompletion) {
|
|
274
276
|
if (this.viewMode === 'view' && fg('platform_synced_block_patch_8')) {
|
|
275
277
|
return;
|
|
276
278
|
}
|
|
@@ -283,6 +285,10 @@ export class SourceSyncBlockStoreManager {
|
|
|
283
285
|
if (!this.dataProvider) {
|
|
284
286
|
throw new Error('Data provider not set');
|
|
285
287
|
}
|
|
288
|
+
if (fg('platform_synced_block_update_refactor')) {
|
|
289
|
+
// add the node to the cache
|
|
290
|
+
this.updateSyncBlockData(node);
|
|
291
|
+
}
|
|
286
292
|
this.creationCompletionCallbacks.set(resourceId, onCompletion);
|
|
287
293
|
(_this$createExperienc = this.createExperience) === null || _this$createExperienc === void 0 ? void 0 : _this$createExperienc.start({});
|
|
288
294
|
this.dataProvider.createNodeData({
|
|
@@ -332,10 +332,12 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
332
332
|
/**
|
|
333
333
|
* Create a bodiedSyncBlock node with empty content to backend
|
|
334
334
|
* @param attrs attributes Ids of the node
|
|
335
|
+
* @param node the ProseMirror node to cache
|
|
336
|
+
* @param onCompletion callback invoked when creation completes
|
|
335
337
|
*/
|
|
336
338
|
}, {
|
|
337
339
|
key: "createBodiedSyncBlockNode",
|
|
338
|
-
value: function createBodiedSyncBlockNode(attrs, onCompletion) {
|
|
340
|
+
value: function createBodiedSyncBlockNode(attrs, node, onCompletion) {
|
|
339
341
|
var _this4 = this;
|
|
340
342
|
if (this.viewMode === 'view' && fg('platform_synced_block_patch_8')) {
|
|
341
343
|
return;
|
|
@@ -347,6 +349,10 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
347
349
|
if (!this.dataProvider) {
|
|
348
350
|
throw new Error('Data provider not set');
|
|
349
351
|
}
|
|
352
|
+
if (fg('platform_synced_block_update_refactor')) {
|
|
353
|
+
// add the node to the cache
|
|
354
|
+
this.updateSyncBlockData(node);
|
|
355
|
+
}
|
|
350
356
|
this.creationCompletionCallbacks.set(resourceId, onCompletion);
|
|
351
357
|
(_this$createExperienc = this.createExperience) === null || _this$createExperienc === void 0 || _this$createExperienc.start({});
|
|
352
358
|
this.dataProvider.createNodeData({
|
|
@@ -57,8 +57,10 @@ export declare class SourceSyncBlockStoreManager {
|
|
|
57
57
|
/**
|
|
58
58
|
* Create a bodiedSyncBlock node with empty content to backend
|
|
59
59
|
* @param attrs attributes Ids of the node
|
|
60
|
+
* @param node the ProseMirror node to cache
|
|
61
|
+
* @param onCompletion callback invoked when creation completes
|
|
60
62
|
*/
|
|
61
|
-
createBodiedSyncBlockNode(attrs: SyncBlockAttrs, onCompletion: OnCompletion): void;
|
|
63
|
+
createBodiedSyncBlockNode(attrs: SyncBlockAttrs, node: PMNode, onCompletion: OnCompletion): void;
|
|
62
64
|
private setPendingDeletion;
|
|
63
65
|
private delete;
|
|
64
66
|
isRetryingDeletion(): boolean;
|
|
@@ -57,8 +57,10 @@ export declare class SourceSyncBlockStoreManager {
|
|
|
57
57
|
/**
|
|
58
58
|
* Create a bodiedSyncBlock node with empty content to backend
|
|
59
59
|
* @param attrs attributes Ids of the node
|
|
60
|
+
* @param node the ProseMirror node to cache
|
|
61
|
+
* @param onCompletion callback invoked when creation completes
|
|
60
62
|
*/
|
|
61
|
-
createBodiedSyncBlockNode(attrs: SyncBlockAttrs, onCompletion: OnCompletion): void;
|
|
63
|
+
createBodiedSyncBlockNode(attrs: SyncBlockAttrs, node: PMNode, onCompletion: OnCompletion): void;
|
|
62
64
|
private setPendingDeletion;
|
|
63
65
|
private delete;
|
|
64
66
|
isRetryingDeletion(): boolean;
|
package/package.json
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@atlaskit/editor-prosemirror": "^7.3.0",
|
|
30
30
|
"@atlaskit/node-data-provider": "^9.0.0",
|
|
31
31
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
32
|
-
"@atlaskit/tmp-editor-statsig": "^54.
|
|
32
|
+
"@atlaskit/tmp-editor-statsig": "^54.4.0",
|
|
33
33
|
"@babel/runtime": "^7.0.0",
|
|
34
34
|
"@compiled/react": "^0.20.0",
|
|
35
35
|
"graphql-ws": "^5.14.2",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"uuid": "^3.1.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@atlaskit/editor-common": "^112.
|
|
41
|
+
"@atlaskit/editor-common": "^112.18.0",
|
|
42
42
|
"react": "^18.2.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"name": "@atlaskit/editor-synced-block-provider",
|
|
84
|
-
"version": "4.3.
|
|
84
|
+
"version": "4.3.3",
|
|
85
85
|
"description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
|
|
86
86
|
"author": "Atlassian Pty Ltd",
|
|
87
87
|
"license": "Apache-2.0",
|