@atlaskit/editor-synced-block-provider 2.2.3 → 2.3.0

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 (29) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cjs/hooks/useFetchSyncBlockData.js +5 -30
  3. package/dist/cjs/providers/syncBlockProvider.js +23 -4
  4. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +319 -63
  5. package/dist/cjs/store-manager/syncBlockStoreManager.js +27 -4
  6. package/dist/cjs/utils/mergeFetchSyncBlockDataResult.js +38 -0
  7. package/dist/es2019/hooks/useFetchSyncBlockData.js +6 -31
  8. package/dist/es2019/providers/syncBlockProvider.js +17 -3
  9. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +172 -44
  10. package/dist/es2019/store-manager/syncBlockStoreManager.js +21 -4
  11. package/dist/es2019/utils/mergeFetchSyncBlockDataResult.js +30 -0
  12. package/dist/esm/hooks/useFetchSyncBlockData.js +6 -31
  13. package/dist/esm/providers/syncBlockProvider.js +21 -2
  14. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +320 -64
  15. package/dist/esm/store-manager/syncBlockStoreManager.js +27 -4
  16. package/dist/esm/utils/mergeFetchSyncBlockDataResult.js +31 -0
  17. package/dist/types/common/schema.d.ts +1 -1
  18. package/dist/types/providers/syncBlockProvider.d.ts +1 -1
  19. package/dist/types/providers/types.d.ts +1 -0
  20. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +24 -8
  21. package/dist/types/store-manager/syncBlockStoreManager.d.ts +12 -4
  22. package/dist/types/utils/mergeFetchSyncBlockDataResult.d.ts +12 -0
  23. package/dist/types-ts4.5/common/schema.d.ts +1 -1
  24. package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +1 -1
  25. package/dist/types-ts4.5/providers/types.d.ts +1 -0
  26. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +24 -8
  27. package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +12 -4
  28. package/dist/types-ts4.5/utils/mergeFetchSyncBlockDataResult.d.ts +12 -0
  29. package/package.json +1 -1
@@ -1,39 +1,14 @@
1
- import { useCallback, useEffect, useState } from 'react';
2
- import { SyncBlockError } from '../common/types';
1
+ import { useEffect, useState } from 'react';
3
2
  export const SYNC_BLOCK_FETCH_INTERVAL = 3000;
4
3
  export const useFetchSyncBlockData = (manager, syncBlockNode) => {
5
4
  const [fetchSyncBlockDataResult, setFetchSyncBlockDataResult] = useState(null);
6
- const fetchSyncBlockNode = useCallback(() => {
7
- manager.fetchSyncBlockData(syncBlockNode).then(data => {
8
- if (data !== null && data !== void 0 && data.error) {
9
- // if there is an error, we don't want to replace real existing data with the error data
10
- setFetchSyncBlockDataResult(prev => {
11
- if (!prev || prev.error) {
12
- return data;
13
- }
14
- return prev;
15
- });
16
- } else {
17
- setFetchSyncBlockDataResult(data !== null && data !== void 0 ? data : null);
18
- }
19
- }).catch(() => {
20
- //TODO: EDITOR-1921 - add error analytics
21
- setFetchSyncBlockDataResult(prev => {
22
- if (!prev || prev.error) {
23
- return {
24
- error: SyncBlockError.Errored
25
- };
26
- }
27
- return prev;
28
- });
29
- });
30
- }, [manager, syncBlockNode]);
31
5
  useEffect(() => {
32
- fetchSyncBlockNode();
33
- const interval = window.setInterval(fetchSyncBlockNode, SYNC_BLOCK_FETCH_INTERVAL);
6
+ const unsubscribe = manager.subscribeToSyncBlockData(syncBlockNode, data => {
7
+ setFetchSyncBlockDataResult(data);
8
+ });
34
9
  return () => {
35
- window.clearInterval(interval);
10
+ unsubscribe();
36
11
  };
37
- }, [fetchSyncBlockNode]);
12
+ }, [manager, setFetchSyncBlockDataResult, syncBlockNode]);
38
13
  return fetchSyncBlockDataResult;
39
14
  };
@@ -1,5 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { useMemo } from 'react';
3
+ import { SyncBlockError } from '../common/types';
3
4
  import { SyncBlockDataProvider } from '../providers/types';
4
5
  import { getLocalIdFromAri, getPageARIFromResourceId } from '../utils/ari';
5
6
  export class SyncBlockProvider extends SyncBlockDataProvider {
@@ -17,9 +18,22 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
17
18
  return node.attrs.localId;
18
19
  }
19
20
  fetchNodesData(nodes) {
20
- return Promise.all(nodes.map(node => {
21
- return this.fetchProvider.fetchData(node.attrs.resourceId);
22
- }));
21
+ const resourceIdSet = new Set(nodes.map(node => node.attrs.resourceId));
22
+ const resourceIds = [...resourceIdSet];
23
+ return Promise.allSettled(resourceIds.map(resourceId => {
24
+ return this.fetchProvider.fetchData(resourceId).then(data => {
25
+ return data;
26
+ }, () => {
27
+ return {
28
+ status: SyncBlockError.Errored,
29
+ resourceId
30
+ };
31
+ });
32
+ })).then(results => {
33
+ return results.filter(result => {
34
+ return result.status === 'fulfilled';
35
+ }).map(result => result.value);
36
+ });
23
37
  }
24
38
 
25
39
  /**
@@ -1,3 +1,5 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { resolveFetchSyncBlockDataResult } from '../utils/mergeFetchSyncBlockDataResult';
1
3
  const createSyncBlockNode = (localId, resourceId) => {
2
4
  return {
3
5
  type: 'syncBlock',
@@ -9,80 +11,206 @@ const createSyncBlockNode = (localId, resourceId) => {
9
11
  };
10
12
  export class ReferenceSyncBlockStoreManager {
11
13
  constructor(dataProvider) {
12
- this.dataProvider = dataProvider;
14
+ _defineProperty(this, "isInitialized", false);
15
+ _defineProperty(this, "isRefreshingSubscriptions", false);
13
16
  this.syncBlockCache = new Map();
17
+ this.subscriptions = new Map();
18
+ this.dataProvider = dataProvider;
14
19
  this.syncBlockURLRequests = new Map();
15
20
  }
21
+ async init(editorView) {
22
+ if (!this.editorView && !this.isInitialized) {
23
+ this.editorView = editorView;
24
+ const syncBlockNodes = editorView.state.doc.children.filter(node => node.type.name === 'syncBlock').map(node => {
25
+ return node.toJSON();
26
+ }) || [];
27
+ if (syncBlockNodes.length > 0) {
28
+ try {
29
+ const dataResults = await this.fetchSyncBlocksData(syncBlockNodes);
30
+ if (!dataResults) {
31
+ throw new Error('No data results returned when initializing sync block store manager');
32
+ }
33
+ dataResults.forEach(dataResult => {
34
+ this.updateCache(dataResult);
35
+ });
36
+ } catch (error) {
37
+ // TODO: EDITOR-1921 - add error analytics
38
+ }
39
+ }
40
+ }
41
+ this.isInitialized = true;
42
+ }
16
43
 
17
44
  /**
18
- *
19
- * @param localId - The local ID of the sync block to get the source URL for
20
- * @param resourceId - The resource ID of the sync block to get the source URL for
21
- * Fetches source URl for a sync block and updates sync block data with the source URL asynchronously.
45
+ * Refreshes the subscriptions for all sync blocks.
46
+ * @returns {Promise<void>}
22
47
  */
23
- fetchSyncBlockSourceURL({
24
- localId,
25
- resourceId
26
- }) {
27
- if (!localId || !resourceId || !this.dataProvider) {
48
+ async refreshSubscriptions() {
49
+ if (this.isRefreshingSubscriptions || !this.isInitialized) {
50
+ return;
51
+ }
52
+ this.isRefreshingSubscriptions = true;
53
+ const syncBlocks = [];
54
+ for (const [resourceId, callbacks] of this.subscriptions.entries()) {
55
+ Object.keys(callbacks).forEach(localId => {
56
+ syncBlocks.push(createSyncBlockNode(localId, resourceId));
57
+ });
58
+ }
59
+ try {
60
+ // fetch latest data for all subscribed sync blocks
61
+ // this function will update the cache and call the subscriptions
62
+ await this.fetchSyncBlocksData(syncBlocks);
63
+ } catch (error) {
64
+ // TODO: EDITOR-1921 - add error analytics
65
+ } finally {
66
+ this.isRefreshingSubscriptions = false;
67
+ }
68
+ }
69
+ fetchSyncBlockSourceURL(resourceId) {
70
+ if (!resourceId || !this.dataProvider) {
28
71
  return;
29
72
  }
30
73
 
31
74
  // if the sync block is a reference block, we need to fetch the URL to the source
32
75
  // we could optimise this further by checking if the sync block is on the same page as the source
33
- if (!this.syncBlockURLRequests.get(localId)) {
34
- this.syncBlockURLRequests.set(localId, true);
35
- this.dataProvider.retrieveSyncBlockSourceUrl(createSyncBlockNode(localId, resourceId)).then(sourceURL => {
36
- const existingSyncBlock = this.syncBlockCache.get(localId);
37
- if (existingSyncBlock) {
38
- existingSyncBlock.sourceURL = sourceURL;
76
+ if (!this.syncBlockURLRequests.get(resourceId)) {
77
+ this.syncBlockURLRequests.set(resourceId, true);
78
+ this.dataProvider.retrieveSyncBlockSourceUrl(createSyncBlockNode('', resourceId)).then(sourceURL => {
79
+ const existingSyncBlock = this.getFromCache(resourceId);
80
+ if (existingSyncBlock && existingSyncBlock.data) {
81
+ existingSyncBlock.data = {
82
+ ...existingSyncBlock.data,
83
+ sourceURL
84
+ };
85
+ this.updateCache(existingSyncBlock);
39
86
  }
40
87
  }).finally(() => {
41
- this.syncBlockURLRequests.set(localId, false);
88
+ this.syncBlockURLRequests.set(resourceId, false);
42
89
  });
43
90
  }
44
91
  }
92
+
93
+ /**
94
+ * Fetch sync block data for a given sync block node.
95
+ * @param syncBlockNode - The sync block node to fetch data for
96
+ * @returns The fetched sync block data result
97
+ */
45
98
  async fetchSyncBlockData(syncBlockNode) {
46
99
  if (!this.dataProvider) {
47
100
  throw new Error('Data provider not set');
48
101
  }
49
102
  const syncNode = createSyncBlockNode(syncBlockNode.attrs.localId, syncBlockNode.attrs.resourceId);
50
-
51
- // async fetch source URL if it is not already fetched
52
- const existingSyncBlock = this.syncBlockCache.get(syncBlockNode.attrs.localId);
53
- if (!(existingSyncBlock !== null && existingSyncBlock !== void 0 && existingSyncBlock.sourceURL)) {
54
- this.fetchSyncBlockSourceURL({
55
- localId: syncBlockNode.attrs.localId,
56
- resourceId: syncBlockNode.attrs.resourceId
57
- });
103
+ const data = await this.fetchSyncBlocksData([syncNode]);
104
+ if (!data || data.length === 0) {
105
+ throw new Error('Failed to fetch sync block data');
58
106
  }
59
- let data;
60
- try {
61
- data = await this.dataProvider.fetchNodesData([syncNode]);
62
- if (!data) {
63
- throw new Error('Failed to fetch sync block node data');
64
- }
65
- } catch (error) {
107
+ return data[0];
108
+ }
109
+ async fetchSyncBlocksData(syncBlockNodes) {
110
+ if (!this.dataProvider) {
111
+ throw new Error('Data provider not set');
112
+ }
113
+ const data = await this.dataProvider.fetchNodesData(syncBlockNodes);
114
+ if (!data) {
66
115
  throw new Error('Failed to fetch sync block node data');
67
116
  }
68
- const fetchSyncBlockDataResult = data[0];
69
- if (!fetchSyncBlockDataResult.error && fetchSyncBlockDataResult.data) {
70
- // only adds it to the map if it did not error out
71
- this.syncBlockCache.set(syncBlockNode.attrs.localId, {
72
- ...existingSyncBlock,
73
- ...fetchSyncBlockDataResult.data
74
- });
117
+ const resolvedData = [];
118
+ data.forEach(fetchSyncBlockDataResult => {
119
+ var _resolvedFetchSyncBlo;
120
+ if (!fetchSyncBlockDataResult.resourceId) {
121
+ return;
122
+ }
123
+ const existingSyncBlock = this.getFromCache(fetchSyncBlockDataResult.resourceId);
124
+ const resolvedFetchSyncBlockDataResult = existingSyncBlock ? resolveFetchSyncBlockDataResult(existingSyncBlock, fetchSyncBlockDataResult) : fetchSyncBlockDataResult;
125
+ this.updateCache(resolvedFetchSyncBlockDataResult);
126
+ resolvedData.push(resolvedFetchSyncBlockDataResult);
127
+
128
+ // fetch source URL if not already present
129
+ if (!((_resolvedFetchSyncBlo = resolvedFetchSyncBlockDataResult.data) !== null && _resolvedFetchSyncBlo !== void 0 && _resolvedFetchSyncBlo.sourceURL) && resolvedFetchSyncBlockDataResult.resourceId) {
130
+ this.fetchSyncBlockSourceURL(resolvedFetchSyncBlockDataResult.resourceId);
131
+ }
132
+ });
133
+ return resolvedData;
134
+ }
135
+ updateCache(syncBlock) {
136
+ const {
137
+ resourceId
138
+ } = syncBlock;
139
+ if (resourceId) {
140
+ this.syncBlockCache.set(resourceId, syncBlock);
141
+ const callbacks = this.subscriptions.get(resourceId);
142
+ if (callbacks) {
143
+ Object.values(callbacks).forEach(callback => {
144
+ callback(syncBlock);
145
+ });
146
+ }
147
+ }
148
+ }
149
+ getFromCache(resourceId) {
150
+ return this.syncBlockCache.get(resourceId);
151
+ }
152
+ deleteFromCache(resourceId) {
153
+ this.syncBlockCache.delete(resourceId);
154
+ }
155
+ subscribe(node, callback) {
156
+ // check node is a sync block, as we only support sync block subscriptions
157
+ if (node.type.name !== 'syncBlock') {
158
+ return () => {};
75
159
  }
76
- return fetchSyncBlockDataResult;
160
+ const {
161
+ resourceId,
162
+ localId
163
+ } = node.attrs;
164
+ if (!localId || !resourceId) {
165
+ return () => {};
166
+ }
167
+
168
+ // add to subscriptions map
169
+ const resourceSubscriptions = this.subscriptions.get(resourceId) || {};
170
+ this.subscriptions.set(resourceId, {
171
+ ...resourceSubscriptions,
172
+ [localId]: callback
173
+ });
174
+
175
+ // call the callback immediately if we have cached data
176
+ const cachedData = this.getFromCache(resourceId);
177
+ if (cachedData) {
178
+ callback(cachedData);
179
+ } else {
180
+ this.fetchSyncBlockData(node).catch(() => {});
181
+ }
182
+ return () => {
183
+ const resourceSubscriptions = this.subscriptions.get(resourceId);
184
+ if (resourceSubscriptions) {
185
+ delete resourceSubscriptions[localId];
186
+ if (Object.keys(resourceSubscriptions).length === 0) {
187
+ this.subscriptions.delete(resourceId);
188
+ this.deleteFromCache(resourceId);
189
+ } else {
190
+ this.subscriptions.set(resourceId, resourceSubscriptions);
191
+ }
192
+ }
193
+ };
77
194
  }
78
195
 
79
196
  /**
80
197
  * Get the URL for a sync block.
81
- * @param localId - The local ID of the sync block to get the URL for
198
+ * @param resourceId - The resource ID of the sync block
82
199
  * @returns
83
200
  */
84
- getSyncBlockURL(localId) {
85
- const syncBlock = this.syncBlockCache.get(localId);
86
- return syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.sourceURL;
201
+ getSyncBlockURL(resourceId) {
202
+ var _syncBlock$data;
203
+ const syncBlock = this.getFromCache(resourceId);
204
+ if (!syncBlock) {
205
+ return undefined;
206
+ }
207
+ return (_syncBlock$data = syncBlock.data) === null || _syncBlock$data === void 0 ? void 0 : _syncBlock$data.sourceURL;
208
+ }
209
+ destroy() {
210
+ this.syncBlockCache.clear();
211
+ this.subscriptions.clear();
212
+ this.syncBlockURLRequests.clear();
213
+ this.editorView = undefined;
214
+ this.isInitialized = false;
87
215
  }
88
216
  }
@@ -11,6 +11,12 @@ export class SyncBlockStoreManager {
11
11
  this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider);
12
12
  this.sourceSyncBlockStoreManager = new SourceSyncBlockStoreManager(dataProvider);
13
13
  }
14
+
15
+ /**
16
+ * Fetch sync block data for a given sync block node.
17
+ * @param syncBlockNode - The sync block node to fetch data for
18
+ * @returns The fetched sync block data result
19
+ */
14
20
  fetchSyncBlockData(syncBlockNode) {
15
21
  if (!['bodiedSyncBlock', 'syncBlock'].includes(syncBlockNode.type.name)) {
16
22
  throw new Error('Node is not a sync block');
@@ -45,16 +51,18 @@ export class SyncBlockStoreManager {
45
51
 
46
52
  /**
47
53
  * Get the URL for a sync block.
48
- * @param localId - The local ID of the sync block to get the URL for
54
+ * @param resourceId - The resource ID of the sync block to get the URL for
49
55
  * @returns
50
56
  */
51
- getSyncBlockURL(localId) {
57
+ getSyncBlockURL(resourceId) {
52
58
  // only applicable to reference sync block, for now (will be refactored further)
53
- return this.referenceSyncBlockStoreManager.getSyncBlockURL(localId);
59
+ return this.referenceSyncBlockStoreManager.getSyncBlockURL(resourceId);
54
60
  }
55
61
  setEditorView(editorView) {
56
- // only applicable to source sync block, for now (will be refactored further)
57
62
  this.sourceSyncBlockStoreManager.setEditorView(editorView);
63
+ if (editorView) {
64
+ this.referenceSyncBlockStoreManager.init(editorView);
65
+ }
58
66
  }
59
67
  isSourceBlock(node) {
60
68
  return node.type.name === 'bodiedSyncBlock';
@@ -71,6 +79,12 @@ export class SyncBlockStoreManager {
71
79
  // only applicable to source sync block, for now (will be refactored further)
72
80
  return this.sourceSyncBlockStoreManager.createSyncBlockNode();
73
81
  }
82
+ subscribeToSyncBlockData(node, callback) {
83
+ return this.referenceSyncBlockStoreManager.subscribe(node, callback);
84
+ }
85
+ refreshSubscriptions() {
86
+ this.referenceSyncBlockStoreManager.refreshSubscriptions();
87
+ }
74
88
  deleteSyncBlocksWithConfirmation(tr, syncBlockIds) {
75
89
  // only applicable to source sync block, for now (will be refactored further)
76
90
  return this.sourceSyncBlockStoreManager.deleteSyncBlocksWithConfirmation(tr, syncBlockIds);
@@ -79,4 +93,7 @@ export class SyncBlockStoreManager {
79
93
  // only applicable to source sync block, for now (will be refactored further)
80
94
  this.sourceSyncBlockStoreManager.rebaseTransaction(incomingTr, state);
81
95
  }
96
+ destroy() {
97
+ this.referenceSyncBlockStoreManager.destroy();
98
+ }
82
99
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Merges two FetchSyncBlockDataResult objects,
3
+ * currently it only preserves the sourceURL from the old result,
4
+ * but this can be extended in the future to preserve other fields and resolve conflicts as needed.
5
+ * e.g. compare timestamps or version numbers to determine which data is more recent.
6
+ *
7
+ * @param oldResult - The existing FetchSyncBlockDataResult object.
8
+ * @param newResult - The new FetchSyncBlockDataResult object to merge.
9
+ * @returns A merged FetchSyncBlockDataResult object.
10
+ */
11
+ export const resolveFetchSyncBlockDataResult = (oldResult, newResult) => {
12
+ var _newResult$data, _oldResult$data;
13
+ // if the old result has no data, we simple return the new result
14
+ if (!oldResult.data) {
15
+ return newResult;
16
+ } else if (!newResult.data) {
17
+ // if the new result has no data, we simply return the old result
18
+ // TODO: EDITOR-2533 - handle this case based on the error type and whether we should keep old data or not
19
+ return oldResult;
20
+ }
21
+
22
+ // otherwise, we merge the two results, preserving the sourceURL from the old result if it exists
23
+ return {
24
+ ...newResult,
25
+ data: {
26
+ ...newResult.data,
27
+ sourceURL: ((_newResult$data = newResult.data) === null || _newResult$data === void 0 ? void 0 : _newResult$data.sourceURL) || ((_oldResult$data = oldResult.data) === null || _oldResult$data === void 0 ? void 0 : _oldResult$data.sourceURL) || undefined
28
+ }
29
+ };
30
+ };
@@ -1,43 +1,18 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
- import { useCallback, useEffect, useState } from 'react';
3
- import { SyncBlockError } from '../common/types';
2
+ import { useEffect, useState } from 'react';
4
3
  export var SYNC_BLOCK_FETCH_INTERVAL = 3000;
5
4
  export var useFetchSyncBlockData = function useFetchSyncBlockData(manager, syncBlockNode) {
6
5
  var _useState = useState(null),
7
6
  _useState2 = _slicedToArray(_useState, 2),
8
7
  fetchSyncBlockDataResult = _useState2[0],
9
8
  setFetchSyncBlockDataResult = _useState2[1];
10
- var fetchSyncBlockNode = useCallback(function () {
11
- manager.fetchSyncBlockData(syncBlockNode).then(function (data) {
12
- if (data !== null && data !== void 0 && data.error) {
13
- // if there is an error, we don't want to replace real existing data with the error data
14
- setFetchSyncBlockDataResult(function (prev) {
15
- if (!prev || prev.error) {
16
- return data;
17
- }
18
- return prev;
19
- });
20
- } else {
21
- setFetchSyncBlockDataResult(data !== null && data !== void 0 ? data : null);
22
- }
23
- }).catch(function () {
24
- //TODO: EDITOR-1921 - add error analytics
25
- setFetchSyncBlockDataResult(function (prev) {
26
- if (!prev || prev.error) {
27
- return {
28
- error: SyncBlockError.Errored
29
- };
30
- }
31
- return prev;
32
- });
33
- });
34
- }, [manager, syncBlockNode]);
35
9
  useEffect(function () {
36
- fetchSyncBlockNode();
37
- var interval = window.setInterval(fetchSyncBlockNode, SYNC_BLOCK_FETCH_INTERVAL);
10
+ var unsubscribe = manager.subscribeToSyncBlockData(syncBlockNode, function (data) {
11
+ setFetchSyncBlockDataResult(data);
12
+ });
38
13
  return function () {
39
- window.clearInterval(interval);
14
+ unsubscribe();
40
15
  };
41
- }, [fetchSyncBlockNode]);
16
+ }, [manager, setFetchSyncBlockDataResult, syncBlockNode]);
42
17
  return fetchSyncBlockDataResult;
43
18
  };
@@ -1,4 +1,5 @@
1
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
3
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
4
  import _createClass from "@babel/runtime/helpers/createClass";
4
5
  import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
@@ -9,6 +10,7 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
9
10
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
10
11
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
11
12
  import { useMemo } from 'react';
13
+ import { SyncBlockError } from '../common/types';
12
14
  import { SyncBlockDataProvider } from '../providers/types';
13
15
  import { getLocalIdFromAri, getPageARIFromResourceId } from '../utils/ari';
14
16
  export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
@@ -37,9 +39,26 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
37
39
  key: "fetchNodesData",
38
40
  value: function fetchNodesData(nodes) {
39
41
  var _this2 = this;
40
- return Promise.all(nodes.map(function (node) {
41
- return _this2.fetchProvider.fetchData(node.attrs.resourceId);
42
+ var resourceIdSet = new Set(nodes.map(function (node) {
43
+ return node.attrs.resourceId;
42
44
  }));
45
+ var resourceIds = _toConsumableArray(resourceIdSet);
46
+ return Promise.allSettled(resourceIds.map(function (resourceId) {
47
+ return _this2.fetchProvider.fetchData(resourceId).then(function (data) {
48
+ return data;
49
+ }, function () {
50
+ return {
51
+ status: SyncBlockError.Errored,
52
+ resourceId: resourceId
53
+ };
54
+ });
55
+ })).then(function (results) {
56
+ return results.filter(function (result) {
57
+ return result.status === 'fulfilled';
58
+ }).map(function (result) {
59
+ return result.value;
60
+ });
61
+ });
43
62
  }
44
63
 
45
64
  /**