@atlaskit/editor-synced-block-provider 3.8.1 → 3.10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-synced-block-provider
2
2
 
3
+ ## 3.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`7638bd91b6c72`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7638bd91b6c72) -
8
+ The errors should render correctly when using batch-retrieve to fetch synced blocks
9
+
10
+ ## 3.9.0
11
+
12
+ ### Minor Changes
13
+
14
+ - [`fe0f9c8de91c3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fe0f9c8de91c3) -
15
+ The batch retrieve of the blocks must also send document ARI and also the local instance ID of the
16
+ reference blocks
17
+
3
18
  ## 3.8.1
4
19
 
5
20
  ### Patch Changes
@@ -137,11 +137,11 @@ var BlockError = exports.BlockError = /*#__PURE__*/function (_Error) {
137
137
  }( /*#__PURE__*/(0, _wrapNativeSuper2.default)(Error));
138
138
  var getSyncedBlockContent = exports.getSyncedBlockContent = /*#__PURE__*/function () {
139
139
  var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(_ref2) {
140
- var blockAri, documentAri, queryParams, response;
140
+ var blockAri, queryParams, response;
141
141
  return _regenerator.default.wrap(function _callee2$(_context2) {
142
142
  while (1) switch (_context2.prev = _context2.next) {
143
143
  case 0:
144
- blockAri = _ref2.blockAri, documentAri = _ref2.documentAri;
144
+ blockAri = _ref2.blockAri;
145
145
  // Disable sending documentAri for now. We'll add it back if we find a way to update references that follows the save & refresh principle.
146
146
  // Slack discussion here: https://atlassian.slack.com/archives/C09DZT1TBNW/p1767836775552099?thread_ts=1767836754.024889&cid=C09DZT1TBNW
147
147
  // const queryParams = documentAri ? `?documentAri=${encodeURIComponent(documentAri)}` : '';
@@ -184,17 +184,21 @@ var getSyncedBlockContent = exports.getSyncedBlockContent = /*#__PURE__*/functio
184
184
  */
185
185
  var batchRetrieveSyncedBlocks = exports.batchRetrieveSyncedBlocks = /*#__PURE__*/function () {
186
186
  var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(_ref4) {
187
- var blockAris, response;
187
+ var blockIdentifiers, documentAri, response;
188
188
  return _regenerator.default.wrap(function _callee3$(_context3) {
189
189
  while (1) switch (_context3.prev = _context3.next) {
190
190
  case 0:
191
- blockAris = _ref4.blockAris;
191
+ blockIdentifiers = _ref4.blockIdentifiers, documentAri = _ref4.documentAri;
192
192
  _context3.next = 3;
193
193
  return (0, _retry.fetchWithRetry)("".concat(BLOCK_SERVICE_API_URL, "/block/batch-retrieve"), {
194
194
  method: 'POST',
195
195
  headers: COMMON_HEADERS,
196
196
  body: JSON.stringify({
197
- blockAris: blockAris
197
+ documentAri: documentAri,
198
+ blockIdentifiers: blockIdentifiers,
199
+ blockAris: blockIdentifiers.map(function (blockIdentifier) {
200
+ return blockIdentifier.blockAri;
201
+ })
198
202
  })
199
203
  });
200
204
  case 3:
@@ -8,7 +8,19 @@ exports.useFetchSyncBlockTitle = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
9
  var _react = require("react");
10
10
  var useFetchSyncBlockTitle = exports.useFetchSyncBlockTitle = function useFetchSyncBlockTitle(manager, syncBlockNode) {
11
- var _useState = (0, _react.useState)(undefined),
11
+ // Initialize state from cache to prevent flickering during re-renders
12
+ var _useState = (0, _react.useState)(function () {
13
+ var _cachedData$data;
14
+ if (syncBlockNode.type.name !== 'syncBlock') {
15
+ return undefined;
16
+ }
17
+ var resourceId = syncBlockNode.attrs.resourceId;
18
+ if (!resourceId) {
19
+ return undefined;
20
+ }
21
+ var cachedData = manager.referenceManager.getFromCache(resourceId);
22
+ return cachedData === null || cachedData === void 0 || (_cachedData$data = cachedData.data) === null || _cachedData$data === void 0 ? void 0 : _cachedData$data.sourceTitle;
23
+ }),
12
24
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
13
25
  sourceTitle = _useState2[0],
14
26
  setSourceTitle = _useState2[1];
@@ -17,7 +17,7 @@ var _ari = require("../../clients/block-service/ari");
17
17
  var _blockService = require("../../clients/block-service/blockService");
18
18
  var _types = require("../../common/types");
19
19
  var _errorHandling = require("../../utils/errorHandling");
20
- var _resourceId3 = require("../../utils/resourceId");
20
+ var _resourceId2 = require("../../utils/resourceId");
21
21
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
22
22
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
23
23
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -43,6 +43,26 @@ var mapBlockError = function mapBlockError(error) {
43
43
  }
44
44
  return _types.SyncBlockError.Errored;
45
45
  };
46
+ var mapErrorResponseCode = function mapErrorResponseCode(errorCode) {
47
+ switch (errorCode) {
48
+ case 'FORBIDDEN':
49
+ return _types.SyncBlockError.Forbidden;
50
+ case 'NOT_FOUND':
51
+ return _types.SyncBlockError.NotFound;
52
+ case 'INVALID_REQUEST':
53
+ return _types.SyncBlockError.InvalidRequest;
54
+ case 'CONFLICT':
55
+ return _types.SyncBlockError.Conflict;
56
+ case 'RATE_LIMITED':
57
+ return _types.SyncBlockError.RateLimited;
58
+ case 'SERVER_ERROR':
59
+ return _types.SyncBlockError.ServerError;
60
+ case 'INVALID_CONTENT':
61
+ return _types.SyncBlockError.InvalidContent;
62
+ default:
63
+ return _types.SyncBlockError.Errored;
64
+ }
65
+ };
46
66
 
47
67
  /**
48
68
  * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
@@ -326,67 +346,84 @@ var BlockServiceADFFetchProvider = /*#__PURE__*/function () {
326
346
 
327
347
  /**
328
348
  * Batch fetches multiple synced blocks by their resource IDs.
329
- * @param resourceIds - Array of resource IDs to fetch
349
+ * @param blockNodeIdentifiers - Array of block node identifiers, containing block instance (local) ID + resource IDs to fetch
330
350
  * @returns Array of SyncBlockInstance results
331
351
  */
332
352
  }, {
333
353
  key: "batchFetchData",
334
354
  value: (function () {
335
- var _batchFetchData = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(resourceIds) {
355
+ var _batchFetchData = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(blockNodeIdentifiers) {
336
356
  var _this2 = this;
337
- var blockAris, validResourceIds, processedResourceIds, response, results, _iterator, _step, blockContentResponse, resourceId, value, syncedBlockData, _iterator2, _step2, errorResponse, _resourceId, _iterator3, _step3, _resourceId2;
357
+ var blockIdentifiers, validResourceIds, processedResourceIds, response, results, _iterator, _step, blockContentResponse, resourceId, value, syncedBlockData, _iterator2, _step2, errorResponse, _resourceId, _iterator3, _step3, blockNodeIdentifier;
338
358
  return _regenerator.default.wrap(function _callee4$(_context4) {
339
359
  while (1) switch (_context4.prev = _context4.next) {
340
360
  case 0:
341
- blockAris = resourceIds.map(function (resourceId) {
342
- return (0, _ari.generateBlockAriFromReference)({
343
- cloudId: _this2.cloudId,
344
- resourceId: resourceId
345
- });
361
+ blockIdentifiers = blockNodeIdentifiers.map(function (blockIdentifier) {
362
+ return {
363
+ blockAri: (0, _ari.generateBlockAriFromReference)({
364
+ cloudId: _this2.cloudId,
365
+ resourceId: blockIdentifier.resourceId
366
+ }),
367
+ blockInstanceId: blockIdentifier.blockInstanceId
368
+ };
346
369
  }); // Create a set of valid resourceIds for validation
347
- validResourceIds = new Set(resourceIds); // Track which resourceIds have been processed
370
+ validResourceIds = new Set(blockNodeIdentifiers.map(function (blockNodeIdentifier) {
371
+ return blockNodeIdentifier.resourceId;
372
+ })); // Track which resourceIds have been processed
348
373
  processedResourceIds = new Set();
349
- _context4.prev = 3;
350
- _context4.next = 6;
374
+ if (this.parentAri) {
375
+ _context4.next = 5;
376
+ break;
377
+ }
378
+ return _context4.abrupt("return", blockNodeIdentifiers.map(function (blockNodeIdentifier) {
379
+ return {
380
+ error: _types.SyncBlockError.Errored,
381
+ resourceId: blockNodeIdentifier.resourceId
382
+ };
383
+ }));
384
+ case 5:
385
+ _context4.prev = 5;
386
+ _context4.next = 8;
351
387
  return (0, _blockService.batchRetrieveSyncedBlocks)({
352
- blockAris: blockAris
388
+ documentAri: this.parentAri,
389
+ blockIdentifiers: blockIdentifiers
353
390
  });
354
- case 6:
391
+ case 8:
355
392
  response = _context4.sent;
356
393
  results = []; // Process successful blocks
357
394
  if (!response.success) {
358
- _context4.next = 33;
395
+ _context4.next = 35;
359
396
  break;
360
397
  }
361
398
  _iterator = _createForOfIteratorHelper(response.success);
362
- _context4.prev = 10;
399
+ _context4.prev = 12;
363
400
  _iterator.s();
364
- case 12:
401
+ case 14:
365
402
  if ((_step = _iterator.n()).done) {
366
- _context4.next = 25;
403
+ _context4.next = 27;
367
404
  break;
368
405
  }
369
406
  blockContentResponse = _step.value;
370
407
  // Extract resourceId from the returned blockAri
371
408
  resourceId = this.extractResourceIdFromBlockAri(blockContentResponse.blockAri);
372
409
  if (!(!resourceId || !validResourceIds.has(resourceId))) {
373
- _context4.next = 17;
410
+ _context4.next = 19;
374
411
  break;
375
412
  }
376
- return _context4.abrupt("continue", 23);
377
- case 17:
413
+ return _context4.abrupt("continue", 25);
414
+ case 19:
378
415
  processedResourceIds.add(resourceId);
379
416
  value = blockContentResponse.content;
380
417
  if (value) {
381
- _context4.next = 22;
418
+ _context4.next = 24;
382
419
  break;
383
420
  }
384
421
  results.push({
385
422
  error: _types.SyncBlockError.NotFound,
386
423
  resourceId: resourceId
387
424
  });
388
- return _context4.abrupt("continue", 23);
389
- case 22:
425
+ return _context4.abrupt("continue", 25);
426
+ case 24:
390
427
  try {
391
428
  syncedBlockData = JSON.parse(value);
392
429
  results.push({
@@ -405,71 +442,71 @@ var BlockServiceADFFetchProvider = /*#__PURE__*/function () {
405
442
  resourceId: resourceId
406
443
  });
407
444
  }
408
- case 23:
409
- _context4.next = 12;
410
- break;
411
445
  case 25:
412
- _context4.next = 30;
446
+ _context4.next = 14;
413
447
  break;
414
448
  case 27:
415
- _context4.prev = 27;
416
- _context4.t0 = _context4["catch"](10);
449
+ _context4.next = 32;
450
+ break;
451
+ case 29:
452
+ _context4.prev = 29;
453
+ _context4.t0 = _context4["catch"](12);
417
454
  _iterator.e(_context4.t0);
418
- case 30:
419
- _context4.prev = 30;
455
+ case 32:
456
+ _context4.prev = 32;
420
457
  _iterator.f();
421
- return _context4.finish(30);
422
- case 33:
458
+ return _context4.finish(32);
459
+ case 35:
423
460
  if (!response.error) {
424
- _context4.next = 54;
461
+ _context4.next = 56;
425
462
  break;
426
463
  }
427
464
  _iterator2 = _createForOfIteratorHelper(response.error);
428
- _context4.prev = 35;
465
+ _context4.prev = 37;
429
466
  _iterator2.s();
430
- case 37:
467
+ case 39:
431
468
  if ((_step2 = _iterator2.n()).done) {
432
- _context4.next = 46;
469
+ _context4.next = 48;
433
470
  break;
434
471
  }
435
472
  errorResponse = _step2.value;
436
473
  // Extract resourceId from the returned blockAri
437
474
  _resourceId = this.extractResourceIdFromBlockAri(errorResponse.blockAri);
438
475
  if (!(!_resourceId || !validResourceIds.has(_resourceId))) {
439
- _context4.next = 42;
476
+ _context4.next = 44;
440
477
  break;
441
478
  }
442
- return _context4.abrupt("continue", 44);
443
- case 42:
479
+ return _context4.abrupt("continue", 46);
480
+ case 44:
444
481
  processedResourceIds.add(_resourceId);
445
482
  results.push({
446
- error: _types.SyncBlockError.Errored,
483
+ error: mapErrorResponseCode(errorResponse.code),
447
484
  resourceId: _resourceId
448
485
  });
449
- case 44:
450
- _context4.next = 37;
451
- break;
452
486
  case 46:
453
- _context4.next = 51;
487
+ _context4.next = 39;
454
488
  break;
455
489
  case 48:
456
- _context4.prev = 48;
457
- _context4.t1 = _context4["catch"](35);
490
+ _context4.next = 53;
491
+ break;
492
+ case 50:
493
+ _context4.prev = 50;
494
+ _context4.t1 = _context4["catch"](37);
458
495
  _iterator2.e(_context4.t1);
459
- case 51:
460
- _context4.prev = 51;
496
+ case 53:
497
+ _context4.prev = 53;
461
498
  _iterator2.f();
462
- return _context4.finish(51);
463
- case 54:
499
+ return _context4.finish(53);
500
+ case 56:
464
501
  // Ensure all resourceIds have a result - return NotFound for any missing ones
465
- _iterator3 = _createForOfIteratorHelper(resourceIds);
502
+ _iterator3 = _createForOfIteratorHelper(blockNodeIdentifiers);
466
503
  try {
467
504
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
468
- _resourceId2 = _step3.value;
469
- if (!processedResourceIds.has(_resourceId2)) {
505
+ blockNodeIdentifier = _step3.value;
506
+ if (!processedResourceIds.has(blockNodeIdentifier.resourceId)) {
470
507
  results.push({
471
508
  error: _types.SyncBlockError.NotFound,
472
- resourceId: _resourceId2
509
+ resourceId: blockNodeIdentifier.resourceId
473
510
  });
474
511
  }
475
512
  }
@@ -479,20 +516,20 @@ var BlockServiceADFFetchProvider = /*#__PURE__*/function () {
479
516
  _iterator3.f();
480
517
  }
481
518
  return _context4.abrupt("return", results);
482
- case 59:
483
- _context4.prev = 59;
484
- _context4.t2 = _context4["catch"](3);
485
- return _context4.abrupt("return", resourceIds.map(function (resourceId) {
519
+ case 61:
520
+ _context4.prev = 61;
521
+ _context4.t2 = _context4["catch"](5);
522
+ return _context4.abrupt("return", blockNodeIdentifiers.map(function (blockNodeIdentifier) {
486
523
  return {
487
524
  error: _context4.t2 instanceof _blockService.BlockError ? mapBlockError(_context4.t2) : _types.SyncBlockError.Errored,
488
- resourceId: resourceId
525
+ resourceId: blockNodeIdentifier.resourceId
489
526
  };
490
527
  }));
491
- case 62:
528
+ case 64:
492
529
  case "end":
493
530
  return _context4.stop();
494
531
  }
495
- }, _callee4, this, [[3, 59], [10, 27, 30, 33], [35, 48, 51, 54]]);
532
+ }, _callee4, this, [[5, 61], [12, 29, 32, 35], [37, 50, 53, 56]]);
496
533
  }));
497
534
  function batchFetchData(_x4) {
498
535
  return _batchFetchData.apply(this, arguments);
@@ -723,7 +760,7 @@ var BlockServiceADFWriteProvider = /*#__PURE__*/function () {
723
760
  }, {
724
761
  key: "generateResourceIdForReference",
725
762
  value: function generateResourceIdForReference(sourceId) {
726
- return (0, _resourceId3.createResourceIdForReference)(this.product, this.parentId || '', sourceId);
763
+ return (0, _resourceId2.createResourceIdForReference)(this.product, this.parentId || '', sourceId);
727
764
  }
728
765
  }, {
729
766
  key: "generateResourceId",
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.useMemoizedSyncedBlockProvider = exports.SyncBlockProvider = void 0;
8
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
9
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
10
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
12
11
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
@@ -88,49 +87,51 @@ var SyncBlockProvider = exports.SyncBlockProvider = /*#__PURE__*/function (_Sync
88
87
  value: (function () {
89
88
  var _fetchNodesData = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(nodes) {
90
89
  var _this2 = this;
91
- var resourceIdSet, resourceIds;
90
+ var blockIdentifiers;
92
91
  return _regenerator.default.wrap(function _callee$(_context) {
93
92
  while (1) switch (_context.prev = _context.next) {
94
93
  case 0:
95
- resourceIdSet = new Set(nodes.map(function (node) {
96
- return node.attrs.resourceId;
97
- }));
98
- resourceIds = (0, _toConsumableArray2.default)(resourceIdSet);
99
- if (!(resourceIds.length === 0)) {
100
- _context.next = 4;
94
+ blockIdentifiers = nodes.map(function (node) {
95
+ return {
96
+ resourceId: node.attrs.resourceId,
97
+ blockInstanceId: node.attrs.localId
98
+ };
99
+ });
100
+ if (!(blockIdentifiers.length === 0)) {
101
+ _context.next = 3;
101
102
  break;
102
103
  }
103
104
  return _context.abrupt("return", []);
104
- case 4:
105
+ case 3:
105
106
  if (!(0, _platformFeatureFlags.fg)('platform_synced_block_dogfooding')) {
106
- _context.next = 16;
107
+ _context.next = 15;
107
108
  break;
108
109
  }
109
- _context.prev = 5;
110
- _context.next = 8;
111
- return this.fetchProvider.batchFetchData(resourceIds);
112
- case 8:
110
+ _context.prev = 4;
111
+ _context.next = 7;
112
+ return this.fetchProvider.batchFetchData(blockIdentifiers);
113
+ case 7:
113
114
  return _context.abrupt("return", _context.sent);
114
- case 11:
115
- _context.prev = 11;
116
- _context.t0 = _context["catch"](5);
117
- return _context.abrupt("return", resourceIds.map(function (resourceId) {
115
+ case 10:
116
+ _context.prev = 10;
117
+ _context.t0 = _context["catch"](4);
118
+ return _context.abrupt("return", blockIdentifiers.map(function (blockIdentifier) {
118
119
  return {
119
120
  error: _types.SyncBlockError.Errored,
120
- resourceId: resourceId
121
+ resourceId: blockIdentifier.resourceId
121
122
  };
122
123
  }));
123
- case 14:
124
- _context.next = 17;
124
+ case 13:
125
+ _context.next = 16;
125
126
  break;
126
- case 16:
127
- return _context.abrupt("return", Promise.allSettled(resourceIds.map(function (resourceId) {
128
- return _this2.fetchProvider.fetchData(resourceId).then(function (data) {
127
+ case 15:
128
+ return _context.abrupt("return", Promise.allSettled(blockIdentifiers.map(function (blockIdentifier) {
129
+ return _this2.fetchProvider.fetchData(blockIdentifier.resourceId).then(function (data) {
129
130
  return data;
130
131
  }, function () {
131
132
  return {
132
133
  error: _types.SyncBlockError.Errored,
133
- resourceId: resourceId
134
+ resourceId: blockIdentifier.resourceId
134
135
  };
135
136
  });
136
137
  })).then(function (results) {
@@ -140,11 +141,11 @@ var SyncBlockProvider = exports.SyncBlockProvider = /*#__PURE__*/function (_Sync
140
141
  return result.value;
141
142
  });
142
143
  }));
143
- case 17:
144
+ case 16:
144
145
  case "end":
145
146
  return _context.stop();
146
147
  }
147
- }, _callee, this, [[5, 11]]);
148
+ }, _callee, this, [[4, 10]]);
148
149
  }));
149
150
  function fetchNodesData(_x) {
150
151
  return _fetchNodesData.apply(this, arguments);
@@ -100,8 +100,8 @@ export class BlockError extends Error {
100
100
  }
101
101
  }
102
102
  export const getSyncedBlockContent = async ({
103
- blockAri,
104
- documentAri
103
+ blockAri
104
+ // documentAri,
105
105
  }) => {
106
106
  // Disable sending documentAri for now. We'll add it back if we find a way to update references that follows the save & refresh principle.
107
107
  // Slack discussion here: https://atlassian.slack.com/archives/C09DZT1TBNW/p1767836775552099?thread_ts=1767836754.024889&cid=C09DZT1TBNW
@@ -126,13 +126,16 @@ export const getSyncedBlockContent = async ({
126
126
  * @returns A promise containing arrays of successfully fetched blocks and any errors encountered
127
127
  */
128
128
  export const batchRetrieveSyncedBlocks = async ({
129
- blockAris
129
+ blockIdentifiers,
130
+ documentAri
130
131
  }) => {
131
132
  const response = await fetchWithRetry(`${BLOCK_SERVICE_API_URL}/block/batch-retrieve`, {
132
133
  method: 'POST',
133
134
  headers: COMMON_HEADERS,
134
135
  body: JSON.stringify({
135
- blockAris
136
+ documentAri,
137
+ blockIdentifiers,
138
+ blockAris: blockIdentifiers.map(blockIdentifier => blockIdentifier.blockAri)
136
139
  })
137
140
  });
138
141
  if (!response.ok) {
@@ -1,6 +1,20 @@
1
1
  import { useEffect, useState } from 'react';
2
2
  export const useFetchSyncBlockTitle = (manager, syncBlockNode) => {
3
- const [sourceTitle, setSourceTitle] = useState(undefined);
3
+ // Initialize state from cache to prevent flickering during re-renders
4
+ const [sourceTitle, setSourceTitle] = useState(() => {
5
+ var _cachedData$data;
6
+ if (syncBlockNode.type.name !== 'syncBlock') {
7
+ return undefined;
8
+ }
9
+ const {
10
+ resourceId
11
+ } = syncBlockNode.attrs;
12
+ if (!resourceId) {
13
+ return undefined;
14
+ }
15
+ const cachedData = manager.referenceManager.getFromCache(resourceId);
16
+ return cachedData === null || cachedData === void 0 ? void 0 : (_cachedData$data = cachedData.data) === null || _cachedData$data === void 0 ? void 0 : _cachedData$data.sourceTitle;
17
+ });
4
18
  useEffect(() => {
5
19
  const unsubscribe = manager.referenceManager.subscribeToSourceTitle(syncBlockNode, title => {
6
20
  setSourceTitle(title);
@@ -26,6 +26,26 @@ const mapBlockError = error => {
26
26
  }
27
27
  return SyncBlockError.Errored;
28
28
  };
29
+ const mapErrorResponseCode = errorCode => {
30
+ switch (errorCode) {
31
+ case 'FORBIDDEN':
32
+ return SyncBlockError.Forbidden;
33
+ case 'NOT_FOUND':
34
+ return SyncBlockError.NotFound;
35
+ case 'INVALID_REQUEST':
36
+ return SyncBlockError.InvalidRequest;
37
+ case 'CONFLICT':
38
+ return SyncBlockError.Conflict;
39
+ case 'RATE_LIMITED':
40
+ return SyncBlockError.RateLimited;
41
+ case 'SERVER_ERROR':
42
+ return SyncBlockError.ServerError;
43
+ case 'INVALID_CONTENT':
44
+ return SyncBlockError.InvalidContent;
45
+ default:
46
+ return SyncBlockError.Errored;
47
+ }
48
+ };
29
49
 
30
50
  /**
31
51
  * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
@@ -236,23 +256,33 @@ class BlockServiceADFFetchProvider {
236
256
 
237
257
  /**
238
258
  * Batch fetches multiple synced blocks by their resource IDs.
239
- * @param resourceIds - Array of resource IDs to fetch
259
+ * @param blockNodeIdentifiers - Array of block node identifiers, containing block instance (local) ID + resource IDs to fetch
240
260
  * @returns Array of SyncBlockInstance results
241
261
  */
242
- async batchFetchData(resourceIds) {
243
- const blockAris = resourceIds.map(resourceId => generateBlockAriFromReference({
244
- cloudId: this.cloudId,
245
- resourceId
262
+ async batchFetchData(blockNodeIdentifiers) {
263
+ const blockIdentifiers = blockNodeIdentifiers.map(blockIdentifier => ({
264
+ blockAri: generateBlockAriFromReference({
265
+ cloudId: this.cloudId,
266
+ resourceId: blockIdentifier.resourceId
267
+ }),
268
+ blockInstanceId: blockIdentifier.blockInstanceId
246
269
  }));
247
270
 
248
271
  // Create a set of valid resourceIds for validation
249
- const validResourceIds = new Set(resourceIds);
272
+ const validResourceIds = new Set(blockNodeIdentifiers.map(blockNodeIdentifier => blockNodeIdentifier.resourceId));
250
273
 
251
274
  // Track which resourceIds have been processed
252
275
  const processedResourceIds = new Set();
276
+ if (!this.parentAri) {
277
+ return blockNodeIdentifiers.map(blockNodeIdentifier => ({
278
+ error: SyncBlockError.Errored,
279
+ resourceId: blockNodeIdentifier.resourceId
280
+ }));
281
+ }
253
282
  try {
254
283
  const response = await batchRetrieveSyncedBlocks({
255
- blockAris
284
+ documentAri: this.parentAri,
285
+ blockIdentifiers
256
286
  });
257
287
  const results = [];
258
288
 
@@ -304,27 +334,27 @@ class BlockServiceADFFetchProvider {
304
334
  }
305
335
  processedResourceIds.add(resourceId);
306
336
  results.push({
307
- error: SyncBlockError.Errored,
337
+ error: mapErrorResponseCode(errorResponse.code),
308
338
  resourceId
309
339
  });
310
340
  }
311
341
  }
312
342
 
313
343
  // Ensure all resourceIds have a result - return NotFound for any missing ones
314
- for (const resourceId of resourceIds) {
315
- if (!processedResourceIds.has(resourceId)) {
344
+ for (const blockNodeIdentifier of blockNodeIdentifiers) {
345
+ if (!processedResourceIds.has(blockNodeIdentifier.resourceId)) {
316
346
  results.push({
317
347
  error: SyncBlockError.NotFound,
318
- resourceId
348
+ resourceId: blockNodeIdentifier.resourceId
319
349
  });
320
350
  }
321
351
  }
322
352
  return results;
323
353
  } catch (error) {
324
354
  // If batch request fails, return error for all resourceIds
325
- return resourceIds.map(resourceId => ({
355
+ return blockNodeIdentifiers.map(blockNodeIdentifier => ({
326
356
  error: error instanceof BlockError ? mapBlockError(error) : SyncBlockError.Errored,
327
- resourceId
357
+ resourceId: blockNodeIdentifier.resourceId
328
358
  }));
329
359
  }
330
360
  }