@atlaskit/editor-synced-block-provider 2.10.1 → 2.10.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 (85) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/{providers → clients}/block-service/ari.js +2 -2
  3. package/dist/cjs/{utils → clients/confluence}/ari.js +6 -6
  4. package/dist/cjs/{utils → clients/confluence}/sourceInfo.js +7 -7
  5. package/dist/cjs/clients/confluence/utils.js +9 -0
  6. package/dist/cjs/hooks/useFetchSyncBlockData.js +5 -6
  7. package/dist/cjs/hooks/useFetchSyncBlockTitle.js +1 -1
  8. package/dist/cjs/hooks/useHandleContentChanges.js +1 -1
  9. package/dist/cjs/index.js +27 -14
  10. package/dist/cjs/providers/block-service/blockServiceAPI.js +4 -4
  11. package/dist/cjs/providers/confluence/confluenceContentAPI.js +33 -26
  12. package/dist/cjs/providers/syncBlockProvider.js +38 -3
  13. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +86 -19
  14. package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +52 -10
  15. package/dist/cjs/store-manager/syncBlockStoreManager.js +14 -157
  16. package/dist/cjs/utils/utils.js +8 -4
  17. package/dist/es2019/{providers → clients}/block-service/ari.js +1 -1
  18. package/dist/es2019/{utils → clients/confluence}/ari.js +5 -5
  19. package/dist/es2019/{utils → clients/confluence}/sourceInfo.js +5 -5
  20. package/dist/es2019/clients/confluence/utils.js +3 -0
  21. package/dist/es2019/hooks/useFetchSyncBlockData.js +5 -6
  22. package/dist/es2019/hooks/useFetchSyncBlockTitle.js +1 -1
  23. package/dist/es2019/hooks/useHandleContentChanges.js +1 -1
  24. package/dist/es2019/index.js +14 -4
  25. package/dist/es2019/providers/block-service/blockServiceAPI.js +4 -4
  26. package/dist/es2019/providers/confluence/confluenceContentAPI.js +19 -13
  27. package/dist/es2019/providers/syncBlockProvider.js +38 -3
  28. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +75 -10
  29. package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +39 -1
  30. package/dist/es2019/store-manager/syncBlockStoreManager.js +12 -117
  31. package/dist/es2019/utils/utils.js +3 -3
  32. package/dist/esm/{providers → clients}/block-service/ari.js +1 -1
  33. package/dist/esm/{utils → clients/confluence}/ari.js +5 -5
  34. package/dist/esm/{utils → clients/confluence}/sourceInfo.js +7 -7
  35. package/dist/esm/clients/confluence/utils.js +3 -0
  36. package/dist/esm/hooks/useFetchSyncBlockData.js +5 -6
  37. package/dist/esm/hooks/useFetchSyncBlockTitle.js +1 -1
  38. package/dist/esm/hooks/useHandleContentChanges.js +1 -1
  39. package/dist/esm/index.js +14 -4
  40. package/dist/esm/providers/block-service/blockServiceAPI.js +4 -4
  41. package/dist/esm/providers/confluence/confluenceContentAPI.js +33 -26
  42. package/dist/esm/providers/syncBlockProvider.js +38 -3
  43. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +87 -19
  44. package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +52 -10
  45. package/dist/esm/store-manager/syncBlockStoreManager.js +14 -157
  46. package/dist/esm/utils/utils.js +7 -3
  47. package/dist/types/{providers → clients}/block-service/ari.d.ts +1 -1
  48. package/dist/types/{utils → clients/block-service}/blockService.d.ts +3 -3
  49. package/dist/types/clients/confluence/ari.d.ts +9 -0
  50. package/dist/types/{utils → clients/confluence}/contentProperty.d.ts +1 -1
  51. package/dist/types/clients/confluence/sourceInfo.d.ts +2 -0
  52. package/dist/types/clients/confluence/utils.d.ts +2 -0
  53. package/dist/types/common/types.d.ts +3 -1
  54. package/dist/types/index.d.ts +5 -4
  55. package/dist/types/providers/syncBlockProvider.d.ts +10 -1
  56. package/dist/types/providers/types.d.ts +20 -8
  57. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +6 -0
  58. package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +17 -1
  59. package/dist/types/store-manager/syncBlockStoreManager.d.ts +4 -59
  60. package/dist/types/utils/utils.d.ts +1 -2
  61. package/dist/types-ts4.5/{providers → clients}/block-service/ari.d.ts +1 -1
  62. package/dist/types-ts4.5/{utils → clients/block-service}/blockService.d.ts +3 -3
  63. package/dist/types-ts4.5/clients/confluence/ari.d.ts +9 -0
  64. package/dist/types-ts4.5/{utils → clients/confluence}/contentProperty.d.ts +1 -1
  65. package/dist/types-ts4.5/clients/confluence/sourceInfo.d.ts +2 -0
  66. package/dist/types-ts4.5/clients/confluence/utils.d.ts +2 -0
  67. package/dist/types-ts4.5/common/types.d.ts +3 -1
  68. package/dist/types-ts4.5/index.d.ts +5 -4
  69. package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +10 -1
  70. package/dist/types-ts4.5/providers/types.d.ts +20 -8
  71. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +6 -0
  72. package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +17 -1
  73. package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +4 -59
  74. package/dist/types-ts4.5/utils/utils.d.ts +1 -2
  75. package/package.json +5 -5
  76. package/dist/types/utils/ari.d.ts +0 -9
  77. package/dist/types/utils/sourceInfo.d.ts +0 -2
  78. package/dist/types-ts4.5/utils/ari.d.ts +0 -9
  79. package/dist/types-ts4.5/utils/sourceInfo.d.ts +0 -2
  80. /package/dist/cjs/{utils → clients/block-service}/blockService.js +0 -0
  81. /package/dist/cjs/{utils → clients/confluence}/contentProperty.js +0 -0
  82. /package/dist/es2019/{utils → clients/block-service}/blockService.js +0 -0
  83. /package/dist/es2019/{utils → clients/confluence}/contentProperty.js +0 -0
  84. /package/dist/esm/{utils → clients/block-service}/blockService.js +0 -0
  85. /package/dist/esm/{utils → clients/confluence}/contentProperty.js +0 -0
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
2
2
  export const useFetchSyncBlockTitle = (manager, syncBlockNode) => {
3
3
  const [sourceTitle, setSourceTitle] = useState(undefined);
4
4
  useEffect(() => {
5
- const unsubscribe = manager.subscribeToSyncBlockSourceTitle(syncBlockNode, title => {
5
+ const unsubscribe = manager.referenceManager.subscribeToSourceTitle(syncBlockNode, title => {
6
6
  setSourceTitle(title);
7
7
  });
8
8
  return () => {
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
2
2
  export const useHandleContentChanges = (manager, syncBlockNode) => {
3
3
  useEffect(() => {
4
4
  try {
5
- manager.updateSyncBlockData(syncBlockNode);
5
+ manager.sourceManager.updateSyncBlockData(syncBlockNode);
6
6
  } catch {
7
7
  //TODO: EDITOR-1921 - add error analytics
8
8
  }
@@ -1,16 +1,26 @@
1
1
  /* eslint-disable @atlaskit/editor/no-re-export */
2
2
 
3
+ // common
3
4
  export { rebaseTransaction } from './common/rebase-transaction';
4
5
  export { SyncBlockError } from './common/types';
6
+ // hooks
5
7
  export { useFetchSyncBlockData } from './hooks/useFetchSyncBlockData';
6
8
  export { useFetchSyncBlockTitle } from './hooks/useFetchSyncBlockTitle';
7
9
  export { useHandleContentChanges } from './hooks/useHandleContentChanges';
8
- export { blockResourceIdFromSourceAndLocalId, getLocalIdFromResourceId } from './providers/block-service/ari';
10
+
11
+ // clients
12
+ export { blockResourceIdFromSourceAndLocalId, getLocalIdFromBlockResourceId } from './clients/block-service/ari';
13
+ export { getConfluencePageAri, getLocalIdFromConfluencePageAri, getPageARIFromContentPropertyResourceId, getPageIdAndTypeFromConfluencePageAri, resourceIdFromConfluencePageSourceIdAndLocalId } from './clients/confluence/ari';
14
+
15
+ // providers
9
16
  export { useMemoizedBlockServiceAPIProviders } from './providers/block-service/blockServiceAPI';
10
17
  export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluence/confluenceContentAPI';
18
+ export { fetchConfluenceSourceInfo } from './clients/confluence/sourceInfo';
11
19
  export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './providers/syncBlockProvider';
20
+ // store managers
12
21
  export { ReferenceSyncBlockStoreManager } from './store-manager/referenceSyncBlockStoreManager';
13
22
  export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
14
- export { getConfluencePageAri, getLocalIdFromAri, getPageARIFromResourceId, getPageIdAndTypeFromAri, resourceIdFromSourceAndLocalId } from './utils/ari';
15
- export { createSyncBlockNode, convertSyncBlockPMNodeToSyncBlockData, convertSyncBlockJSONNodeToSyncBlockNode } from './utils/utils';
16
- export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
23
+
24
+ // utils
25
+ export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
26
+ export { createSyncBlockNode, convertSyncBlockPMNodeToSyncBlockData, convertSyncBlockJSONNodeToSyncBlockNode, convertPMNodesToSyncBlockNodes } from './utils/utils';
@@ -1,8 +1,8 @@
1
1
  import { useMemo } from 'react';
2
+ import { blockResourceIdFromSourceAndLocalId, getLocalIdFromBlockResourceId } from '../../clients/block-service/ari';
3
+ import { BlockError, createSyncedBlock, deleteSyncedBlock, getSyncedBlockContent, updateSyncedBlock } from '../../clients/block-service/blockService';
2
4
  import { SyncBlockError } from '../../common/types';
3
- import { BlockError, createSyncedBlock, deleteSyncedBlock, getSyncedBlockContent, updateSyncedBlock } from '../../utils/blockService';
4
5
  import { stringifyError } from '../../utils/errorHandling';
5
- import { blockResourceIdFromSourceAndLocalId, getLocalIdFromResourceId } from './ari';
6
6
  const mapBlockError = error => {
7
7
  switch (error.status) {
8
8
  case 403:
@@ -20,7 +20,7 @@ class BlockServiceADFFetchProvider {
20
20
  // resourceId is the ARI of the block. E.G ari:cloud:blocks:site-123:synced-block/uuid-456
21
21
  // in the content API provider, this was the concatenation of the source document's ARI and the local ID. E.G ari:cloud:confluence:site-123:page/pageId/uuid-456
22
22
  async fetchData(resourceId) {
23
- const localId = getLocalIdFromResourceId(resourceId);
23
+ const localId = getLocalIdFromBlockResourceId(resourceId);
24
24
  try {
25
25
  const blockContentResponse = await getSyncedBlockContent({
26
26
  blockAri: resourceId
@@ -59,7 +59,7 @@ class BlockServiceADFFetchProvider {
59
59
  retrieveSourceInfoFetchData(resourceId, pageARI) {
60
60
  let sourceLocalId;
61
61
  try {
62
- sourceLocalId = getLocalIdFromResourceId(resourceId);
62
+ sourceLocalId = getLocalIdFromBlockResourceId(resourceId);
63
63
  } catch (error) {
64
64
  // EDITOR-1921: log analytic here, safe to continue
65
65
  }
@@ -1,10 +1,10 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { useMemo } from 'react';
3
+ import { getConfluencePageAri, getPageARIFromContentPropertyResourceId, getLocalIdFromConfluencePageAri, getPageIdAndTypeFromConfluencePageAri, resourceIdFromConfluencePageSourceIdAndLocalId } from '../../clients/confluence/ari';
4
+ import { getContentProperty, createContentProperty, updateContentProperty, deleteContentProperty } from '../../clients/confluence/contentProperty';
5
+ import { isBlogPageType } from '../../clients/confluence/utils';
3
6
  import { SyncBlockError } from '../../common/types';
4
- import { getLocalIdFromAri, getPageARIFromResourceId, getPageIdAndTypeFromAri, resourceIdFromSourceAndLocalId } from '../../utils/ari';
5
- import { getContentProperty, createContentProperty, updateContentProperty, deleteContentProperty } from '../../utils/contentProperty';
6
7
  import { stringifyError } from '../../utils/errorHandling';
7
- import { isBlogPageType } from '../../utils/utils';
8
8
 
9
9
  /**
10
10
  * Configuration for Content API providers
@@ -51,8 +51,8 @@ class ConfluenceADFFetchProvider {
51
51
  const {
52
52
  id: pageId,
53
53
  type: pageType
54
- } = getPageIdAndTypeFromAri(resourceId);
55
- const localId = getLocalIdFromAri(resourceId);
54
+ } = getPageIdAndTypeFromConfluencePageAri(resourceId);
55
+ const localId = getLocalIdFromConfluencePageAri(resourceId);
56
56
  try {
57
57
  const key = getContentPropertyKey(this.config.contentPropertyKey, localId);
58
58
  const options = {
@@ -99,10 +99,10 @@ class ConfluenceADFFetchProvider {
99
99
  }
100
100
  }
101
101
  retrieveSourceInfoFetchData(resourceId) {
102
- const pageARI = getPageARIFromResourceId(resourceId);
102
+ const pageARI = getPageARIFromContentPropertyResourceId(resourceId);
103
103
  let sourceLocalId;
104
104
  try {
105
- sourceLocalId = getLocalIdFromAri(resourceId);
105
+ sourceLocalId = getLocalIdFromConfluencePageAri(resourceId);
106
106
  } catch (error) {
107
107
  // EDITOR-1921: log analytic here, safe to continue
108
108
  }
@@ -152,7 +152,7 @@ class ConfluenceADFWriteProvider {
152
152
  resourceId
153
153
  } = data;
154
154
  try {
155
- match = getPageIdAndTypeFromAri(data.resourceId);
155
+ match = getPageIdAndTypeFromConfluencePageAri(data.resourceId);
156
156
  } catch (error) {
157
157
  return {
158
158
  error: stringifyError(error)
@@ -164,12 +164,18 @@ class ConfluenceADFWriteProvider {
164
164
  } = match;
165
165
  try {
166
166
  // Update existing content property
167
- const localId = getLocalIdFromAri(resourceId);
167
+ const localId = getLocalIdFromConfluencePageAri(resourceId);
168
168
  const key = getContentPropertyKey(this.config.contentPropertyKey, localId);
169
+ const sourceAri = getConfluencePageAri(pageId, this.config.cloudId, pageType);
170
+ const syncBlockDataWithSourceDocumentAri = {
171
+ ...data,
172
+ product: 'confluence-page',
173
+ sourceAri
174
+ };
169
175
  const options = {
170
176
  pageId,
171
177
  key,
172
- value: data,
178
+ value: syncBlockDataWithSourceDocumentAri,
173
179
  cloudId: this.config.cloudId,
174
180
  pageType
175
181
  };
@@ -203,7 +209,7 @@ class ConfluenceADFWriteProvider {
203
209
  async deleteData(resourceId) {
204
210
  let deletePayload, deleteResult, match;
205
211
  try {
206
- match = getPageIdAndTypeFromAri(resourceId);
212
+ match = getPageIdAndTypeFromConfluencePageAri(resourceId);
207
213
  } catch (error) {
208
214
  return {
209
215
  resourceId,
@@ -216,7 +222,7 @@ class ConfluenceADFWriteProvider {
216
222
  type: pageType
217
223
  } = match;
218
224
  try {
219
- const localId = getLocalIdFromAri(resourceId);
225
+ const localId = getLocalIdFromConfluencePageAri(resourceId);
220
226
  const key = getContentPropertyKey(this.config.contentPropertyKey, localId);
221
227
  const options = {
222
228
  pageId,
@@ -241,7 +247,7 @@ class ConfluenceADFWriteProvider {
241
247
  };
242
248
  }
243
249
  generateResourceId(sourceId, localId) {
244
- return resourceIdFromSourceAndLocalId(sourceId, localId);
250
+ return resourceIdFromConfluencePageSourceIdAndLocalId(sourceId, localId);
245
251
  }
246
252
  }
247
253
 
@@ -1,8 +1,9 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { useMemo } from 'react';
3
+ import { getPageIdAndTypeFromConfluencePageAri } from '../clients/confluence/ari';
4
+ import { fetchConfluenceSourceInfo } from '../clients/confluence/sourceInfo';
3
5
  import { SyncBlockError } from '../common/types';
4
6
  import { SyncBlockDataProvider } from '../providers/types';
5
- import { fetchSourceInfo } from '../utils/sourceInfo';
6
7
  export class SyncBlockProvider extends SyncBlockDataProvider {
7
8
  // the source document ARI; that the source sync block is on.
8
9
 
@@ -137,7 +138,7 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
137
138
  * @returns The source info
138
139
  */
139
140
  retrieveSyncBlockSourceInfo(node) {
140
- // with content API, this is the concatenation of the page ARI and the block's localId.
141
+ // with content API, this is the concatenation of the page ARI and the block's localId.
141
142
  // with block service, this is the ARI of the block.
142
143
  // this can be cleaned up from the specific providers and placed here after platform_synced_blocks_block_service_provider
143
144
  const {
@@ -154,7 +155,10 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
154
155
  return Promise.reject(error);
155
156
  }
156
157
  }
157
- return pageARI ? fetchSourceInfo(pageARI, sourceLocalId) : Promise.resolve(undefined);
158
+
159
+ // TODO: EDITOR-3312 - based on the source sync block product,
160
+ // execute fetchConfluenceSourceInfo or fetchJiraItemSourceInfo or similar...
161
+ return pageARI ? fetchConfluenceSourceInfo(pageARI, sourceLocalId) : Promise.resolve(undefined);
158
162
  }
159
163
  generateResourceId(sourceId, localId) {
160
164
  return this.writeProvider.generateResourceId(sourceId, localId);
@@ -168,6 +172,37 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
168
172
  getSyncedBlockRendererProviderOptions() {
169
173
  return this.providerOptions;
170
174
  }
175
+
176
+ /**
177
+ * Retrieve the parent info for the sync block
178
+ *
179
+ * @param resourceId
180
+ * @param syncBlockInstance
181
+ *
182
+ * @returns The parent info for the sync block
183
+ */
184
+ retrieveSyncBlockParentInfo(syncBlockInstance) {
185
+ if (!syncBlockInstance || !syncBlockInstance.data) {
186
+ return undefined;
187
+ }
188
+ const {
189
+ sourceAri,
190
+ product
191
+ } = syncBlockInstance.data;
192
+ if (!sourceAri || !product) {
193
+ return undefined;
194
+ }
195
+
196
+ // TODO: EDITOR-3312 - based on the source sync block product,
197
+ // execute getPageIdAndTypeFromConfluencePageAri or getJiraItemIdAndTypeFromJiraItemAri or similar...
198
+ const {
199
+ id: contentId
200
+ } = getPageIdAndTypeFromConfluencePageAri(sourceAri);
201
+ return {
202
+ contentId,
203
+ contentProduct: product
204
+ };
205
+ }
171
206
  }
172
207
  export const useMemoizedSyncedBlockProvider = (fetchProvider, writeProvider, sourceId, providerOptions) => {
173
208
  return useMemo(() => {
@@ -3,6 +3,12 @@ import { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
3
3
  import { SyncBlockError } from '../common/types';
4
4
  import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
5
5
  import { createSyncBlockNode } from '../utils/utils';
6
+
7
+ // A store manager responsible for the lifecycle and state management of reference sync blocks in an editor instance.
8
+ // Designed to manage local in-memory state and synchronize with an external data provider.
9
+ // Supports fetch, cache, and subscription for sync block data.
10
+ // Handles fetching source URL and title for sync blocks.
11
+ // Can be used in both editor and renderer contexts.
6
12
  export class ReferenceSyncBlockStoreManager {
7
13
  constructor(dataProvider) {
8
14
  _defineProperty(this, "isRefreshingSubscriptions", false);
@@ -44,6 +50,8 @@ export class ReferenceSyncBlockStoreManager {
44
50
  return;
45
51
  }
46
52
 
53
+ // TODO: EDITOR-3312 - retrieve the source info based on the source sync block product
54
+
47
55
  // if the sync block is a reference block, we need to fetch the URL to the source
48
56
  // we could optimise this further by checking if the sync block is on the same page as the source
49
57
  if (!this.syncBlockURLRequests.get(resourceId)) {
@@ -66,7 +74,16 @@ export class ReferenceSyncBlockStoreManager {
66
74
  });
67
75
  }
68
76
  }
77
+
78
+ /**
79
+ * Fetch sync block data for a given array of sync block nodes.
80
+ * @param syncBlockNodes - The array of sync block nodes to fetch data for
81
+ * @returns The fetched sync block data results
82
+ */
69
83
  async fetchSyncBlocksData(syncBlockNodes) {
84
+ if (syncBlockNodes.length === 0) {
85
+ return Promise.resolve([]);
86
+ }
70
87
  if (!this.dataProvider) {
71
88
  throw new Error('Data provider not set');
72
89
  }
@@ -235,26 +252,74 @@ export class ReferenceSyncBlockStoreManager {
235
252
  return undefined;
236
253
  }
237
254
  const {
238
- parentDataProviders
255
+ parentDataProviders,
256
+ providerCreator
239
257
  } = this.dataProvider.getSyncedBlockRendererProviderOptions();
240
- if (!this.providerFactories.has(resourceId)) {
241
- // TODO: EDITOR-2771 - In follow up PR, create media & emoji providers per ref sync block
242
- // The media & emoji providers will be set later, once we get ref sync block data with page ID
243
- // So we need to keep the reference to the Provider Factory so we can then set media & emoji providers later
244
- this.providerFactories.set(resourceId, ProviderFactory.create({
245
- emojiProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.emojiProvider,
246
- mediaProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mediaProvider,
258
+ let providerFactory = this.providerFactories.get(resourceId);
259
+ if (!providerFactory) {
260
+ providerFactory = ProviderFactory.create({
247
261
  mentionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mentionProvider,
248
262
  profilecardProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.profilecardProvider,
249
263
  taskDecisionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider
250
- }));
264
+ });
265
+ this.providerFactories.set(resourceId, providerFactory);
266
+ }
267
+ if (providerCreator) {
268
+ this.retrieveDynamicProviders(resourceId, providerFactory, providerCreator);
269
+ }
270
+ return providerFactory;
271
+ }
272
+ retrieveDynamicProviders(resourceId, providerFactory, providerCreator) {
273
+ if (!this.dataProvider) {
274
+ return;
275
+ }
276
+ const hasMediaProvider = providerFactory.hasProvider('mediaProvider');
277
+ const hasEmojiProvider = providerFactory.hasProvider('emojiProvider');
278
+ if (hasMediaProvider && hasEmojiProvider) {
279
+ return;
280
+ }
281
+ const parentInfo = this.dataProvider.retrieveSyncBlockParentInfo(this.syncBlockCache.get(resourceId));
282
+ if (!parentInfo) {
283
+ return;
284
+ }
285
+ const {
286
+ contentId,
287
+ contentProduct
288
+ } = parentInfo;
289
+ if (!hasMediaProvider) {
290
+ if (providerCreator.createMediaProvider && contentId && contentProduct) {
291
+ const mediaProvider = providerCreator.createMediaProvider({
292
+ contentProduct,
293
+ contentId
294
+ });
295
+ if (mediaProvider) {
296
+ providerFactory.setProvider('mediaProvider', mediaProvider);
297
+ }
298
+ }
299
+ }
300
+ if (!hasEmojiProvider) {
301
+ if (providerCreator.createEmojiProvider && contentId && contentProduct) {
302
+ const emojiProvider = providerCreator.createEmojiProvider({
303
+ contentProduct,
304
+ contentId
305
+ });
306
+ if (emojiProvider) {
307
+ providerFactory.setProvider('emojiProvider', emojiProvider);
308
+ }
309
+ }
251
310
  }
252
- return this.providerFactories.get(resourceId);
253
311
  }
254
312
  destroy() {
313
+ this.dataProvider = undefined;
255
314
  this.syncBlockCache.clear();
256
315
  this.subscriptions.clear();
316
+ this.titleSubscriptions.clear();
257
317
  this.syncBlockURLRequests.clear();
258
318
  this.providerFactories.clear();
319
+ this.isRefreshingSubscriptions = false;
320
+ this.providerFactories.forEach(providerFactory => {
321
+ providerFactory.destroy();
322
+ });
323
+ this.providerFactories.clear();
259
324
  }
260
325
  }
@@ -3,6 +3,11 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
3
  import uuid from 'uuid';
4
4
  import { rebaseTransaction } from '../common/rebase-transaction';
5
5
  import { convertSyncBlockPMNodeToSyncBlockData, createBodiedSyncBlockNode } from '../utils/utils';
6
+ // A store manager responsible for the lifecycle and state management of source sync blocks in an editor instance.
7
+ // Designed to manage local in-memory state and synchronize with an external data provider.
8
+ // Supports create, flush, and delete operations for source sync blocks.
9
+ // Handles caching, debouncing updates, and publish/subscribe for local changes.
10
+ // Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
6
11
  export class SourceSyncBlockStoreManager {
7
12
  constructor(dataProvider) {
8
13
  _defineProperty(this, "setPendingDeletion", (Ids, value) => {
@@ -14,12 +19,18 @@ export class SourceSyncBlockStoreManager {
14
19
  this.dataProvider = dataProvider;
15
20
  this.syncBlockCache = new Map();
16
21
  }
22
+ isSourceBlock(node) {
23
+ return node.type.name === 'bodiedSyncBlock';
24
+ }
17
25
 
18
26
  /**
19
27
  * Add/update a sync block node to/from the local cache
20
28
  * @param syncBlockNode - The sync block node to update
21
29
  */
22
30
  updateSyncBlockData(syncBlockNode) {
31
+ if (!this.isSourceBlock(syncBlockNode)) {
32
+ throw new Error('Invalid sync block node type provided for updateSyncBlockData');
33
+ }
23
34
  const {
24
35
  localId,
25
36
  resourceId
@@ -37,7 +48,7 @@ export class SourceSyncBlockStoreManager {
37
48
  *
38
49
  * @returns true if saving all nodes successfully, false if fail to save some/all nodes
39
50
  */
40
- async flushBodiedSyncBlocks() {
51
+ async flush() {
41
52
  try {
42
53
  if (!this.dataProvider) {
43
54
  throw new Error('Data provider not set');
@@ -73,6 +84,10 @@ export class SourceSyncBlockStoreManager {
73
84
  registerPendingCreation(resourceId) {
74
85
  this.pendingResourceId = resourceId;
75
86
  }
87
+
88
+ /**
89
+ * Register callback function (which inserts node, handles focus etc) to be used later when creation to backend succeed
90
+ */
76
91
  registerCreationCallback(callback) {
77
92
  this.creationCallback = callback;
78
93
  }
@@ -88,6 +103,11 @@ export class SourceSyncBlockStoreManager {
88
103
  this.pendingResourceId = undefined;
89
104
  this.creationCallback = undefined;
90
105
  }
106
+
107
+ /**
108
+ *
109
+ * @returns true if waiting for the result of saving new bodiedSyncBlock to backend
110
+ */
91
111
  hasPendingCreation() {
92
112
  return !!this.pendingResourceId;
93
113
  }
@@ -100,6 +120,10 @@ export class SourceSyncBlockStoreManager {
100
120
  requireConfirmationBeforeDelete() {
101
121
  return !!this.confirmationCallback;
102
122
  }
123
+
124
+ /**
125
+ * @returns attributes for a new bodiedSyncBlock node
126
+ */
103
127
  generateBodiedSyncBlockAttrs() {
104
128
  var _this$dataProvider;
105
129
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
@@ -114,6 +138,11 @@ export class SourceSyncBlockStoreManager {
114
138
  localId
115
139
  };
116
140
  }
141
+
142
+ /**
143
+ * Create a bodiedSyncBlock node with empty content to backend
144
+ * @param attrs attributes Ids of the node
145
+ */
117
146
  createBodiedSyncBlockNode(attrs) {
118
147
  try {
119
148
  if (!this.dataProvider) {
@@ -190,4 +219,13 @@ export class SourceSyncBlockStoreManager {
190
219
  }
191
220
  this.confirmationTransaction = rebaseTransaction(this.confirmationTransaction, incomingTr, state);
192
221
  }
222
+ destroy() {
223
+ this.syncBlockCache.clear();
224
+ this.confirmationCallback = undefined;
225
+ this.confirmationTransaction = undefined;
226
+ this.pendingResourceId = undefined;
227
+ this.creationCallback = undefined;
228
+ this.dataProvider = undefined;
229
+ this.editorView = undefined;
230
+ }
193
231
  }
@@ -1,131 +1,26 @@
1
- import { convertPMNodeToSyncBlockNode } from '../utils/utils';
2
1
  import { ReferenceSyncBlockStoreManager } from './referenceSyncBlockStoreManager';
3
2
  import { SourceSyncBlockStoreManager } from './sourceSyncBlockStoreManager';
4
3
 
5
- // A store manager responsible for the lifecycle and state management of sync blocks in an editor instance.
6
- // Supports create, read, update, and delete operations for sync blocks.
7
- // Designed to manage local in-memory state and synchronize with an external data provider.
8
- // Handles caching, debouncing updates, and publish/subscribe for local changes.
9
- // Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
4
+ // A parent store manager responsible for the lifecycle and state management of sync blocks in an editor instance.
5
+ // Contains two child store managers: ReferenceSyncBlockStoreManager and SourceSyncBlockStoreManager.
6
+ // ReferenceSyncBlockStoreManager is responsible for the lifecycle and state management of reference sync blocks in an editor instance.
7
+ // SourceSyncBlockStoreManager is responsible for the lifecycle and state management of source sync blocks in an editor instance.
8
+ // Can be used in both editor and renderer contexts.
10
9
  export class SyncBlockStoreManager {
11
10
  constructor(dataProvider) {
12
- this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider);
11
+ // In future, if reference manager needs to reach to source manager and read it's current in memorey cache
12
+ // we can pass the source manager as a parameter to the reference manager constructor
13
13
  this.sourceSyncBlockStoreManager = new SourceSyncBlockStoreManager(dataProvider);
14
+ this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider);
14
15
  }
15
-
16
- /**
17
- * Fetch sync block data for a given array of sync block nodes.
18
- * @param nodes - The array of sync block nodes to fetch data for
19
- * @returns The fetched sync block data results
20
- */
21
- fetchSyncBlocksData(nodes) {
22
- const syncBlockNodes = nodes.map(node => convertPMNodeToSyncBlockNode(node)).filter(node => node !== undefined) || [];
23
- if (syncBlockNodes.length === 0) {
24
- return Promise.resolve([]);
25
- }
26
- return this.referenceSyncBlockStoreManager.fetchSyncBlocksData(syncBlockNodes);
27
- }
28
- getReferenceSyncBlockStoreManager() {
16
+ get referenceManager() {
29
17
  return this.referenceSyncBlockStoreManager;
30
18
  }
31
-
32
- /**
33
- * Add/update a sync block node to/from the local cache
34
- * @param syncBlockNode - The sync block node to update
35
- */
36
- updateSyncBlockData(syncBlockNode) {
37
- if (this.isSourceBlock(syncBlockNode)) {
38
- return this.sourceSyncBlockStoreManager.updateSyncBlockData(syncBlockNode);
39
- } else {
40
- throw new Error('Invalid sync block node type provided for updateSyncBlockData');
41
- }
42
- }
43
-
44
- /**
45
- * Save content of bodiedSyncBlock nodes in local cache to backend
46
- *
47
- * @returns true if saving all nodes successfully, false if fail to save some/all nodes
48
- */
49
- flushBodiedSyncBlocks() {
50
- // only applicable to source sync block, for now (will be refactored further)
51
- return this.sourceSyncBlockStoreManager.flushBodiedSyncBlocks();
52
- }
53
-
54
- /**
55
- * Get the URL for a sync block.
56
- * @param resourceId - The resource ID of the sync block to get the URL for
57
- * @returns
58
- */
59
- getSyncBlockURL(resourceId) {
60
- // only applicable to reference sync block, for now (will be refactored further)
61
- return this.referenceSyncBlockStoreManager.getSyncBlockURL(resourceId);
62
- }
63
- setEditorView(editorView) {
64
- this.sourceSyncBlockStoreManager.setEditorView(editorView);
65
- }
66
- isSourceBlock(node) {
67
- return node.type.name === 'bodiedSyncBlock';
68
- }
69
- registerConfirmationCallback(callback) {
70
- // only applicable to source sync block, for now (will be refactored further)
71
- return this.sourceSyncBlockStoreManager.registerConfirmationCallback(callback);
72
- }
73
- requireConfirmationBeforeDelete() {
74
- // only applicable to source sync block, for now (will be refactored further)
75
- return this.sourceSyncBlockStoreManager.requireConfirmationBeforeDelete();
76
- }
77
-
78
- /**
79
- * Register callback function (which inserts node, handles focus etc) to be used later when creation to backend succeed
80
- */
81
- registerCreationCallback(callback) {
82
- this.sourceSyncBlockStoreManager.registerCreationCallback(callback);
83
- }
84
-
85
- /**
86
- *
87
- * @returns true if waiting for the result of saving new bodiedSyncBlock to backend
88
- */
89
- hasPendingCreation() {
90
- return this.sourceSyncBlockStoreManager.hasPendingCreation();
91
- }
92
-
93
- /**
94
- * @returns attributes for a new bodiedSyncBlock node
95
- */
96
- generateBodiedSyncBlockAttrs() {
97
- return this.sourceSyncBlockStoreManager.generateBodiedSyncBlockAttrs();
98
- }
99
-
100
- /**
101
- * Save bodiedSyncBlock with empty content to backend
102
- * @param attrs attributes Ids of the node
103
- */
104
- createBodiedSyncBlockNode(attrs) {
105
- // only applicable to source sync block, for now (will be refactored further)
106
- return this.sourceSyncBlockStoreManager.createBodiedSyncBlockNode(attrs);
107
- }
108
- subscribeToSyncBlockData(node, callback) {
109
- return this.referenceSyncBlockStoreManager.subscribe(node, callback);
110
- }
111
- subscribeToSyncBlockSourceTitle(node, callback) {
112
- return this.referenceSyncBlockStoreManager.subscribeToSourceTitle(node, callback);
113
- }
114
- refreshSubscriptions() {
115
- this.referenceSyncBlockStoreManager.refreshSubscriptions();
116
- }
117
- deleteSyncBlocksWithConfirmation(tr, syncBlockIds) {
118
- // only applicable to source sync block, for now (will be refactored further)
119
- return this.sourceSyncBlockStoreManager.deleteSyncBlocksWithConfirmation(tr, syncBlockIds);
120
- }
121
- rebaseTransaction(incomingTr, state) {
122
- // only applicable to source sync block, for now (will be refactored further)
123
- this.sourceSyncBlockStoreManager.rebaseTransaction(incomingTr, state);
124
- }
125
- getReferenceSyncBlockProviderFactory(resourceId) {
126
- return this.referenceSyncBlockStoreManager.getProviderFactory(resourceId);
19
+ get sourceManager() {
20
+ return this.sourceSyncBlockStoreManager;
127
21
  }
128
22
  destroy() {
129
23
  this.referenceSyncBlockStoreManager.destroy();
24
+ this.sourceSyncBlockStoreManager.destroy();
130
25
  }
131
26
  }
@@ -5,9 +5,6 @@ export const convertSyncBlockPMNodeToSyncBlockData = node => {
5
5
  resourceId: node.attrs.resourceId
6
6
  };
7
7
  };
8
- export const isBlogPageType = pageType => {
9
- return pageType === 'blogpost';
10
- };
11
8
  export const createSyncBlockNode = (localId, resourceId) => {
12
9
  return {
13
10
  type: 'syncBlock',
@@ -38,4 +35,7 @@ export const convertPMNodeToSyncBlockNode = node => {
38
35
  return undefined;
39
36
  }
40
37
  return createSyncBlockNode(node.attrs.localId, node.attrs.resourceId);
38
+ };
39
+ export const convertPMNodesToSyncBlockNodes = nodes => {
40
+ return nodes.map(node => convertPMNodeToSyncBlockNode(node)).filter(node => node !== undefined) || [];
41
41
  };
@@ -19,7 +19,7 @@ export var blockResourceIdFromSourceAndLocalId = function blockResourceIdFromSou
19
19
  * @param ari - the block ARI. E.G ari:cloud:blocks:cloudId:synced-block/localId
20
20
  * @returns the localId of the block node. A randomly generated UUID
21
21
  */
22
- export var getLocalIdFromResourceId = function getLocalIdFromResourceId(ari) {
22
+ export var getLocalIdFromBlockResourceId = function getLocalIdFromBlockResourceId(ari) {
23
23
  var match = ari.match(/ari:cloud:blocks:[^:]+:synced-block\/([a-zA-Z0-9-]+)/);
24
24
  if (match !== null && match !== void 0 && match[1]) {
25
25
  return match[1];