@atlaskit/editor-synced-block-provider 3.4.1 → 3.5.1

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.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`19ca45d2afec9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/19ca45d2afec9) -
8
+ EDITOR-3596 Fix mentions and profile card in Synced Blocks in Jira Renderer
9
+ - Updated dependencies
10
+
11
+ ## 3.5.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`25da5a5d67a2a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/25da5a5d67a2a) -
16
+ EDITOR-2257 implement resourceId conversion and enable SSR
17
+
3
18
  ## 3.4.1
4
19
 
5
20
  ### Patch Changes
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.useMemoizedBlockServiceFetchOnlyAPIProvider = exports.useMemoizedBlockServiceAPIProviders = exports.fetchReferences = exports.createBlockServiceFetchOnlyAPIProvider = exports.createBlockServiceAPIProviders = void 0;
7
+ exports.useMemoizedBlockServiceFetchOnlyAPIProvider = exports.useMemoizedBlockServiceAPIProviders = exports.fetchReferences = exports.createBlockServiceFetchOnlyAPIProvider = exports.createBlockServiceAPIProviders = exports.convertToSyncBlockData = exports.blockAriToResourceId = void 0;
8
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
9
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
10
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
@@ -39,6 +39,32 @@ var mapBlockError = function mapBlockError(error) {
39
39
  return _types.SyncBlockError.Errored;
40
40
  };
41
41
 
42
+ /**
43
+ * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
44
+ *
45
+ * Document ARI format from Block Service API:
46
+ * "ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}"
47
+ *
48
+ * ResourceId format (extracted from ARI):
49
+ * "{product}/{parentId}/{resourceId}" (the full path after synced-block/)
50
+ *
51
+ * Example in context:
52
+ * Input: "ari:cloud:blocks:{uuid}:synced-block/confluence-page/{pageId}/{resourceId}"
53
+ * Output: "confluence-page/{pageId}/{resourceId}"
54
+ *
55
+ * @param blockAri - The block ARI string from Block Service API
56
+ * @returns The ResourceId (full path after synced-block/)
57
+ */
58
+ var blockAriToResourceId = exports.blockAriToResourceId = function blockAriToResourceId(blockAri) {
59
+ // Validate ARI format and extract resourceId using regex
60
+ // Format: ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}
61
+ // The regex captures the full path after synced-block/
62
+ // e.g. ari:cloud:blocks:DUMMY-a5a01d21-1cc3-4f29-9565-f2bb8cd969f5:synced-block/confluence-page/455232061495/e8cf64e3-1b6e-489b-ad86-8465b0905bb4
63
+ // should return confluence-page/455232061495/e8cf64e3-1b6e-489b-ad86-8465b0905bb4
64
+ var match = blockAri.match(/^ari:cloud:blocks:.*:synced-block\/(.+)$/);
65
+ return (match === null || match === void 0 ? void 0 : match[1]) || null;
66
+ };
67
+
42
68
  // convert BlockContentResponse to SyncBlockData
43
69
  // throws exception if JSON parsing fails
44
70
  // what's missing from BlockContentResponse to SyncBlockData:
@@ -46,9 +72,9 @@ var mapBlockError = function mapBlockError(error) {
46
72
  // - sourceURL
47
73
  // - sourceTitle
48
74
  // - isSynced
49
- var convertToSyncBlockData = function convertToSyncBlockData(data) {
75
+ var convertToSyncBlockData = exports.convertToSyncBlockData = function convertToSyncBlockData(data, resourceId) {
50
76
  var createdAt;
51
- if (data.createdAt) {
77
+ if (data.createdAt !== undefined && data.createdAt !== null) {
52
78
  try {
53
79
  // BE returns microseconds, convert to milliseconds
54
80
  // BE should fix this in the future
@@ -65,7 +91,7 @@ var convertToSyncBlockData = function convertToSyncBlockData(data) {
65
91
  createdAt: createdAt,
66
92
  createdBy: data.createdBy,
67
93
  product: data.product,
68
- resourceId: data.blockAri,
94
+ resourceId: resourceId,
69
95
  sourceAri: data.sourceAri
70
96
  };
71
97
  };
@@ -96,9 +122,17 @@ var fetchReferences = exports.fetchReferences = /*#__PURE__*/function () {
96
122
  _ref2 = response || {}, blocks = _ref2.blocks, errors = _ref2.errors;
97
123
  blocksInstances = (blocks || []).map(function (blockContentResponse) {
98
124
  try {
125
+ var resourceId = blockAriToResourceId(blockContentResponse.blockAri);
126
+ if (!resourceId) {
127
+ // could not extract resourceId from blockAri, return InvalidContent error
128
+ return {
129
+ error: _types.SyncBlockError.InvalidContent,
130
+ resourceId: blockContentResponse.blockAri
131
+ };
132
+ }
99
133
  return {
100
- data: convertToSyncBlockData(blockContentResponse),
101
- resourceId: blockContentResponse.blockAri
134
+ data: convertToSyncBlockData(blockContentResponse, resourceId),
135
+ resourceId: resourceId
102
136
  };
103
137
  } catch (_unused) {
104
138
  // JSON parsing error, return InvalidContent error
@@ -391,7 +391,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
391
391
  // When a block is moved, the old component unmounts before the new one mounts.
392
392
  // By delaying deletion, we give the new component time to subscribe and
393
393
  // cancel this pending deletion, preserving the cached data.
394
- // TODO: EDITOR-4152 - Rework this logic
394
+ // TODO: EDITOR-4152 - Rework this logic
395
395
  var deletionTimeout = setTimeout(function () {
396
396
  // Only delete if still no subscribers (wasn't re-subscribed)
397
397
  if (!_this3.subscriptions.has(resourceId)) {
@@ -504,6 +504,16 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
504
504
  taskDecisionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider
505
505
  });
506
506
  this.providerFactories.set(resourceId, providerFactory);
507
+ } else {
508
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.mentionProvider) {
509
+ providerFactory.setProvider('mentionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mentionProvider);
510
+ }
511
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.profilecardProvider) {
512
+ providerFactory.setProvider('profilecardProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.profilecardProvider);
513
+ }
514
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.taskDecisionProvider) {
515
+ providerFactory.setProvider('taskDecisionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider);
516
+ }
507
517
  }
508
518
  if (providerCreator) {
509
519
  try {
@@ -25,6 +25,32 @@ const mapBlockError = error => {
25
25
  return SyncBlockError.Errored;
26
26
  };
27
27
 
28
+ /**
29
+ * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
30
+ *
31
+ * Document ARI format from Block Service API:
32
+ * "ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}"
33
+ *
34
+ * ResourceId format (extracted from ARI):
35
+ * "{product}/{parentId}/{resourceId}" (the full path after synced-block/)
36
+ *
37
+ * Example in context:
38
+ * Input: "ari:cloud:blocks:{uuid}:synced-block/confluence-page/{pageId}/{resourceId}"
39
+ * Output: "confluence-page/{pageId}/{resourceId}"
40
+ *
41
+ * @param blockAri - The block ARI string from Block Service API
42
+ * @returns The ResourceId (full path after synced-block/)
43
+ */
44
+ export const blockAriToResourceId = blockAri => {
45
+ // Validate ARI format and extract resourceId using regex
46
+ // Format: ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}
47
+ // The regex captures the full path after synced-block/
48
+ // e.g. ari:cloud:blocks:DUMMY-a5a01d21-1cc3-4f29-9565-f2bb8cd969f5:synced-block/confluence-page/455232061495/e8cf64e3-1b6e-489b-ad86-8465b0905bb4
49
+ // should return confluence-page/455232061495/e8cf64e3-1b6e-489b-ad86-8465b0905bb4
50
+ const match = blockAri.match(/^ari:cloud:blocks:.*:synced-block\/(.+)$/);
51
+ return (match === null || match === void 0 ? void 0 : match[1]) || null;
52
+ };
53
+
28
54
  // convert BlockContentResponse to SyncBlockData
29
55
  // throws exception if JSON parsing fails
30
56
  // what's missing from BlockContentResponse to SyncBlockData:
@@ -32,9 +58,9 @@ const mapBlockError = error => {
32
58
  // - sourceURL
33
59
  // - sourceTitle
34
60
  // - isSynced
35
- const convertToSyncBlockData = data => {
61
+ export const convertToSyncBlockData = (data, resourceId) => {
36
62
  let createdAt;
37
- if (data.createdAt) {
63
+ if (data.createdAt !== undefined && data.createdAt !== null) {
38
64
  try {
39
65
  // BE returns microseconds, convert to milliseconds
40
66
  // BE should fix this in the future
@@ -51,7 +77,7 @@ const convertToSyncBlockData = data => {
51
77
  createdAt,
52
78
  createdBy: data.createdBy,
53
79
  product: data.product,
54
- resourceId: data.blockAri,
80
+ resourceId,
55
81
  sourceAri: data.sourceAri
56
82
  };
57
83
  };
@@ -71,9 +97,17 @@ export const fetchReferences = async documentAri => {
71
97
  } = response || {};
72
98
  const blocksInstances = (blocks || []).map(blockContentResponse => {
73
99
  try {
100
+ const resourceId = blockAriToResourceId(blockContentResponse.blockAri);
101
+ if (!resourceId) {
102
+ // could not extract resourceId from blockAri, return InvalidContent error
103
+ return {
104
+ error: SyncBlockError.InvalidContent,
105
+ resourceId: blockContentResponse.blockAri
106
+ };
107
+ }
74
108
  return {
75
- data: convertToSyncBlockData(blockContentResponse),
76
- resourceId: blockContentResponse.blockAri
109
+ data: convertToSyncBlockData(blockContentResponse, resourceId),
110
+ resourceId
77
111
  };
78
112
  } catch {
79
113
  // JSON parsing error, return InvalidContent error
@@ -273,7 +273,7 @@ export class ReferenceSyncBlockStoreManager {
273
273
  // When a block is moved, the old component unmounts before the new one mounts.
274
274
  // By delaying deletion, we give the new component time to subscribe and
275
275
  // cancel this pending deletion, preserving the cached data.
276
- // TODO: EDITOR-4152 - Rework this logic
276
+ // TODO: EDITOR-4152 - Rework this logic
277
277
  const deletionTimeout = setTimeout(() => {
278
278
  // Only delete if still no subscribers (wasn't re-subscribed)
279
279
  if (!this.subscriptions.has(resourceId)) {
@@ -383,6 +383,16 @@ export class ReferenceSyncBlockStoreManager {
383
383
  taskDecisionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider
384
384
  });
385
385
  this.providerFactories.set(resourceId, providerFactory);
386
+ } else {
387
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.mentionProvider) {
388
+ providerFactory.setProvider('mentionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mentionProvider);
389
+ }
390
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.profilecardProvider) {
391
+ providerFactory.setProvider('profilecardProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.profilecardProvider);
392
+ }
393
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.taskDecisionProvider) {
394
+ providerFactory.setProvider('taskDecisionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider);
395
+ }
386
396
  }
387
397
  if (providerCreator) {
388
398
  try {
@@ -33,6 +33,32 @@ var mapBlockError = function mapBlockError(error) {
33
33
  return SyncBlockError.Errored;
34
34
  };
35
35
 
36
+ /**
37
+ * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
38
+ *
39
+ * Document ARI format from Block Service API:
40
+ * "ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}"
41
+ *
42
+ * ResourceId format (extracted from ARI):
43
+ * "{product}/{parentId}/{resourceId}" (the full path after synced-block/)
44
+ *
45
+ * Example in context:
46
+ * Input: "ari:cloud:blocks:{uuid}:synced-block/confluence-page/{pageId}/{resourceId}"
47
+ * Output: "confluence-page/{pageId}/{resourceId}"
48
+ *
49
+ * @param blockAri - The block ARI string from Block Service API
50
+ * @returns The ResourceId (full path after synced-block/)
51
+ */
52
+ export var blockAriToResourceId = function blockAriToResourceId(blockAri) {
53
+ // Validate ARI format and extract resourceId using regex
54
+ // Format: ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}
55
+ // The regex captures the full path after synced-block/
56
+ // e.g. ari:cloud:blocks:DUMMY-a5a01d21-1cc3-4f29-9565-f2bb8cd969f5:synced-block/confluence-page/455232061495/e8cf64e3-1b6e-489b-ad86-8465b0905bb4
57
+ // should return confluence-page/455232061495/e8cf64e3-1b6e-489b-ad86-8465b0905bb4
58
+ var match = blockAri.match(/^ari:cloud:blocks:.*:synced-block\/(.+)$/);
59
+ return (match === null || match === void 0 ? void 0 : match[1]) || null;
60
+ };
61
+
36
62
  // convert BlockContentResponse to SyncBlockData
37
63
  // throws exception if JSON parsing fails
38
64
  // what's missing from BlockContentResponse to SyncBlockData:
@@ -40,9 +66,9 @@ var mapBlockError = function mapBlockError(error) {
40
66
  // - sourceURL
41
67
  // - sourceTitle
42
68
  // - isSynced
43
- var convertToSyncBlockData = function convertToSyncBlockData(data) {
69
+ export var convertToSyncBlockData = function convertToSyncBlockData(data, resourceId) {
44
70
  var createdAt;
45
- if (data.createdAt) {
71
+ if (data.createdAt !== undefined && data.createdAt !== null) {
46
72
  try {
47
73
  // BE returns microseconds, convert to milliseconds
48
74
  // BE should fix this in the future
@@ -59,7 +85,7 @@ var convertToSyncBlockData = function convertToSyncBlockData(data) {
59
85
  createdAt: createdAt,
60
86
  createdBy: data.createdBy,
61
87
  product: data.product,
62
- resourceId: data.blockAri,
88
+ resourceId: resourceId,
63
89
  sourceAri: data.sourceAri
64
90
  };
65
91
  };
@@ -90,9 +116,17 @@ export var fetchReferences = /*#__PURE__*/function () {
90
116
  _ref2 = response || {}, blocks = _ref2.blocks, errors = _ref2.errors;
91
117
  blocksInstances = (blocks || []).map(function (blockContentResponse) {
92
118
  try {
119
+ var resourceId = blockAriToResourceId(blockContentResponse.blockAri);
120
+ if (!resourceId) {
121
+ // could not extract resourceId from blockAri, return InvalidContent error
122
+ return {
123
+ error: SyncBlockError.InvalidContent,
124
+ resourceId: blockContentResponse.blockAri
125
+ };
126
+ }
93
127
  return {
94
- data: convertToSyncBlockData(blockContentResponse),
95
- resourceId: blockContentResponse.blockAri
128
+ data: convertToSyncBlockData(blockContentResponse, resourceId),
129
+ resourceId: resourceId
96
130
  };
97
131
  } catch (_unused) {
98
132
  // JSON parsing error, return InvalidContent error
@@ -385,7 +385,7 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
385
385
  // When a block is moved, the old component unmounts before the new one mounts.
386
386
  // By delaying deletion, we give the new component time to subscribe and
387
387
  // cancel this pending deletion, preserving the cached data.
388
- // TODO: EDITOR-4152 - Rework this logic
388
+ // TODO: EDITOR-4152 - Rework this logic
389
389
  var deletionTimeout = setTimeout(function () {
390
390
  // Only delete if still no subscribers (wasn't re-subscribed)
391
391
  if (!_this3.subscriptions.has(resourceId)) {
@@ -498,6 +498,16 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
498
498
  taskDecisionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider
499
499
  });
500
500
  this.providerFactories.set(resourceId, providerFactory);
501
+ } else {
502
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.mentionProvider) {
503
+ providerFactory.setProvider('mentionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mentionProvider);
504
+ }
505
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.profilecardProvider) {
506
+ providerFactory.setProvider('profilecardProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.profilecardProvider);
507
+ }
508
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.taskDecisionProvider) {
509
+ providerFactory.setProvider('taskDecisionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider);
510
+ }
501
511
  }
502
512
  if (providerCreator) {
503
513
  try {
@@ -1,5 +1,24 @@
1
+ import { type BlockContentResponse } from '../../clients/block-service/blockService';
1
2
  import { SyncBlockError, type ResourceId, type SyncBlockAttrs, type SyncBlockData, type SyncBlockProduct } from '../../common/types';
2
3
  import type { ADFFetchProvider, ADFWriteProvider, DeleteSyncBlockResult, SyncBlockInstance, UpdateReferenceSyncBlockResult, WriteSyncBlockResult } from '../types';
4
+ /**
5
+ * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
6
+ *
7
+ * Document ARI format from Block Service API:
8
+ * "ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}"
9
+ *
10
+ * ResourceId format (extracted from ARI):
11
+ * "{product}/{parentId}/{resourceId}" (the full path after synced-block/)
12
+ *
13
+ * Example in context:
14
+ * Input: "ari:cloud:blocks:{uuid}:synced-block/confluence-page/{pageId}/{resourceId}"
15
+ * Output: "confluence-page/{pageId}/{resourceId}"
16
+ *
17
+ * @param blockAri - The block ARI string from Block Service API
18
+ * @returns The ResourceId (full path after synced-block/)
19
+ */
20
+ export declare const blockAriToResourceId: (blockAri: string) => ResourceId | null;
21
+ export declare const convertToSyncBlockData: (data: BlockContentResponse, resourceId: ResourceId) => SyncBlockData;
3
22
  export declare const fetchReferences: (documentAri: string) => Promise<SyncBlockInstance[] | SyncBlockError>;
4
23
  interface BlockServiceADFFetchProviderProps {
5
24
  cloudId: string;
@@ -1,5 +1,24 @@
1
+ import { type BlockContentResponse } from '../../clients/block-service/blockService';
1
2
  import { SyncBlockError, type ResourceId, type SyncBlockAttrs, type SyncBlockData, type SyncBlockProduct } from '../../common/types';
2
3
  import type { ADFFetchProvider, ADFWriteProvider, DeleteSyncBlockResult, SyncBlockInstance, UpdateReferenceSyncBlockResult, WriteSyncBlockResult } from '../types';
4
+ /**
5
+ * Extracts the ResourceId from a block ARI by returning the full path after synced-block/.
6
+ *
7
+ * Document ARI format from Block Service API:
8
+ * "ari:cloud:blocks:{uuid}:synced-block/{product}/{parentId}/{resourceId}"
9
+ *
10
+ * ResourceId format (extracted from ARI):
11
+ * "{product}/{parentId}/{resourceId}" (the full path after synced-block/)
12
+ *
13
+ * Example in context:
14
+ * Input: "ari:cloud:blocks:{uuid}:synced-block/confluence-page/{pageId}/{resourceId}"
15
+ * Output: "confluence-page/{pageId}/{resourceId}"
16
+ *
17
+ * @param blockAri - The block ARI string from Block Service API
18
+ * @returns The ResourceId (full path after synced-block/)
19
+ */
20
+ export declare const blockAriToResourceId: (blockAri: string) => ResourceId | null;
21
+ export declare const convertToSyncBlockData: (data: BlockContentResponse, resourceId: ResourceId) => SyncBlockData;
3
22
  export declare const fetchReferences: (documentAri: string) => Promise<SyncBlockInstance[] | SyncBlockError>;
4
23
  interface BlockServiceADFFetchProviderProps {
5
24
  cloudId: string;
package/package.json CHANGED
@@ -34,7 +34,7 @@
34
34
  "uuid": "^3.1.0"
35
35
  },
36
36
  "peerDependencies": {
37
- "@atlaskit/editor-common": "^111.2.0",
37
+ "@atlaskit/editor-common": "^111.6.0",
38
38
  "react": "^18.2.0"
39
39
  },
40
40
  "devDependencies": {
@@ -77,7 +77,7 @@
77
77
  }
78
78
  },
79
79
  "name": "@atlaskit/editor-synced-block-provider",
80
- "version": "3.4.1",
80
+ "version": "3.5.1",
81
81
  "description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
82
82
  "author": "Atlassian Pty Ltd",
83
83
  "license": "Apache-2.0",