@atlaskit/editor-synced-block-provider 4.4.2 → 4.5.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,23 @@
1
1
  # @atlaskit/editor-synced-block-provider
2
2
 
3
+ ## 4.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`81ae8b16d6c35`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/81ae8b16d6c35) -
8
+ [ux] Allows reference sync blocks with media load it correctly in Confluence when source sync
9
+ block is in Jira.
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
15
+ ## 4.4.3
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies
20
+
3
21
  ## 4.4.2
4
22
 
5
23
  ### Patch Changes
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.fetchJiraMediaToken = void 0;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
12
+ var _retry = require("../../utils/retry");
13
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
15
+ var COMMON_HEADERS = {
16
+ 'Content-Type': 'application/json',
17
+ Accept: 'application/json'
18
+ };
19
+ var AGG_HEADERS = {
20
+ 'X-ExperimentalApi': 'confluence-agg-beta'
21
+ };
22
+ var GRAPHQL_ENDPOINT = '/gateway/api/graphql';
23
+ var JIRA_MEDIA_READ_TOKEN_MAX_TOKEN_LENGTH = 2048;
24
+ var GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_GET_JIRA_MEDIA_TOKEN';
25
+ var GET_JIRA_MEDIA_READ_TOKEN_QUERY = "query ".concat(GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME, "($issueAri: ID!, $maxTokenLength: Int!) {\n jira {\n issueById(id: $issueAri) {\n mediaReadToken(maxTokenLength: $maxTokenLength) @optIn(to: \"JiraMediaReadTokenInIssue\") {\n clientId\n endpointUrl\n tokenLifespanInSeconds\n tokensWithFiles {\n edges {\n node {\n token\n }\n }\n }\n }\n }\n }\n}");
26
+ var getJiraMediaReadToken = /*#__PURE__*/function () {
27
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(issueAri) {
28
+ var bodyData, response;
29
+ return _regenerator.default.wrap(function _callee$(_context) {
30
+ while (1) switch (_context.prev = _context.next) {
31
+ case 0:
32
+ bodyData = {
33
+ query: GET_JIRA_MEDIA_READ_TOKEN_QUERY,
34
+ operationName: GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME,
35
+ variables: {
36
+ issueAri: issueAri,
37
+ maxTokenLength: JIRA_MEDIA_READ_TOKEN_MAX_TOKEN_LENGTH
38
+ }
39
+ };
40
+ _context.next = 3;
41
+ return (0, _retry.fetchWithRetry)(GRAPHQL_ENDPOINT, {
42
+ method: 'POST',
43
+ headers: _objectSpread(_objectSpread({}, COMMON_HEADERS), AGG_HEADERS),
44
+ body: JSON.stringify(bodyData)
45
+ });
46
+ case 3:
47
+ response = _context.sent;
48
+ if (response.ok) {
49
+ _context.next = 6;
50
+ break;
51
+ }
52
+ throw new Error("Failed to get Jira media read token: ".concat(response.statusText));
53
+ case 6:
54
+ _context.next = 8;
55
+ return response.json();
56
+ case 8:
57
+ return _context.abrupt("return", _context.sent);
58
+ case 9:
59
+ case "end":
60
+ return _context.stop();
61
+ }
62
+ }, _callee);
63
+ }));
64
+ return function getJiraMediaReadToken(_x) {
65
+ return _ref.apply(this, arguments);
66
+ };
67
+ }();
68
+
69
+ /**
70
+ * Fetches a media read token for a Jira issue, to allow media uploaded to Jira
71
+ * to be rendered in cross-product synced block references (e.g. in Confluence).
72
+ *
73
+ * @param issueAri - the Jira issue ARI (e.g. ari:cloud:jira:{cloudId}:issue/{issueId})
74
+ * @returns TokenData with token, config (clientId + fileStoreUrl), and optional collectionId
75
+ */
76
+ var fetchJiraMediaToken = exports.fetchJiraMediaToken = /*#__PURE__*/function () {
77
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(issueAri) {
78
+ var _response$data, _mediaReadToken$token, _mediaReadToken$token2, response, mediaReadToken, clientId, endpointUrl, token, errorMsg;
79
+ return _regenerator.default.wrap(function _callee2$(_context2) {
80
+ while (1) switch (_context2.prev = _context2.next) {
81
+ case 0:
82
+ _context2.prev = 0;
83
+ _context2.next = 3;
84
+ return getJiraMediaReadToken(issueAri);
85
+ case 3:
86
+ response = _context2.sent;
87
+ mediaReadToken = (_response$data = response.data) === null || _response$data === void 0 || (_response$data = _response$data.jira) === null || _response$data === void 0 || (_response$data = _response$data.issueById) === null || _response$data === void 0 ? void 0 : _response$data.mediaReadToken;
88
+ clientId = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : mediaReadToken.clientId;
89
+ endpointUrl = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : mediaReadToken.endpointUrl; // Use the first available token from tokensWithFiles, or fall back to empty string.
90
+ // A generic read token (without specific file IDs) is sufficient for rendering.
91
+ token = (_mediaReadToken$token = mediaReadToken === null || mediaReadToken === void 0 || (_mediaReadToken$token2 = mediaReadToken.tokensWithFiles) === null || _mediaReadToken$token2 === void 0 || (_mediaReadToken$token2 = _mediaReadToken$token2.edges) === null || _mediaReadToken$token2 === void 0 || (_mediaReadToken$token2 = _mediaReadToken$token2[0]) === null || _mediaReadToken$token2 === void 0 || (_mediaReadToken$token2 = _mediaReadToken$token2.node) === null || _mediaReadToken$token2 === void 0 ? void 0 : _mediaReadToken$token2.token) !== null && _mediaReadToken$token !== void 0 ? _mediaReadToken$token : '';
92
+ if (!(!clientId || !endpointUrl)) {
93
+ _context2.next = 10;
94
+ break;
95
+ }
96
+ throw new Error('Missing clientId or endpointUrl');
97
+ case 10:
98
+ return _context2.abrupt("return", {
99
+ config: {
100
+ clientId: clientId,
101
+ fileStoreUrl: endpointUrl
102
+ },
103
+ token: token
104
+ });
105
+ case 13:
106
+ _context2.prev = 13;
107
+ _context2.t0 = _context2["catch"](0);
108
+ (0, _monitoring.logException)(_context2.t0, {
109
+ location: 'editor-synced-block-provider/fetchJiraMediaToken'
110
+ });
111
+ errorMsg = _context2.t0 instanceof Error ? _context2.t0.message : String(_context2.t0);
112
+ throw new Error("Failed to get Jira media read token: ".concat(errorMsg));
113
+ case 18:
114
+ case "end":
115
+ return _context2.stop();
116
+ }
117
+ }, _callee2, null, [[0, 13]]);
118
+ }));
119
+ return function fetchJiraMediaToken(_x2) {
120
+ return _ref2.apply(this, arguments);
121
+ };
122
+ }();
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.requiresCrossProductAuth = exports.fetchTokenForSourceProduct = void 0;
7
+ var _fetchMediaToken = require("./confluence/fetchMediaToken");
8
+ var _fetchMediaToken2 = require("./jira/fetchMediaToken");
9
+ var requiresCrossProductAuth = exports.requiresCrossProductAuth = function requiresCrossProductAuth(_ref) {
10
+ var hostProduct = _ref.hostProduct,
11
+ sourceProduct = _ref.sourceProduct;
12
+ return !!sourceProduct && sourceProduct !== hostProduct;
13
+ };
14
+ var fetchTokenForSourceProduct = exports.fetchTokenForSourceProduct = function fetchTokenForSourceProduct(_ref2) {
15
+ var contentId = _ref2.contentId,
16
+ sourceProduct = _ref2.sourceProduct;
17
+ switch (sourceProduct) {
18
+ case 'confluence-page':
19
+ return (0, _fetchMediaToken.fetchMediaToken)(contentId);
20
+ case 'jira-work-item':
21
+ return (0, _fetchMediaToken2.fetchJiraMediaToken)(contentId);
22
+ default:
23
+ throw new Error("Unsupported source product for token fetch: ".concat(sourceProduct));
24
+ }
25
+ };
@@ -432,7 +432,10 @@ var SyncedBlockProvider = exports.SyncedBlockProvider = /*#__PURE__*/function (_
432
432
  contentProduct: sourceProduct
433
433
  };
434
434
  case 'jira-work-item':
435
- throw new Error('Jira work item source product not supported');
435
+ return {
436
+ contentId: sourceAri,
437
+ contentProduct: sourceProduct
438
+ };
436
439
  default:
437
440
  throw new Error("".concat(sourceProduct, " source product not supported"));
438
441
  }
@@ -73,6 +73,7 @@ var SyncBlockProviderFactoryManager = exports.SyncBlockProviderFactoryManager =
73
73
  }, {
74
74
  key: "getSSRProviders",
75
75
  value: function getSSRProviders(resourceId) {
76
+ var _syncBlock$data;
76
77
  var dataProvider = this.deps.getDataProvider();
77
78
  if (!dataProvider) {
78
79
  return null;
@@ -88,6 +89,14 @@ var SyncBlockProviderFactoryManager = exports.SyncBlockProviderFactoryManager =
88
89
  }
89
90
  var contentId = parsedResourceId.contentId,
90
91
  contentProduct = parsedResourceId.product;
92
+ var syncBlock = this.deps.getFromCache(resourceId);
93
+ if (syncBlock !== null && syncBlock !== void 0 && (_syncBlock$data = syncBlock.data) !== null && _syncBlock$data !== void 0 && _syncBlock$data.sourceAri && syncBlock.data.product) {
94
+ var parentInfo = dataProvider.retrieveSyncBlockParentInfo(syncBlock.data.sourceAri, syncBlock.data.product);
95
+ if (parentInfo) {
96
+ contentId = parentInfo.contentId;
97
+ contentProduct = parentInfo.contentProduct;
98
+ }
99
+ }
91
100
  try {
92
101
  var mediaProvider = providerCreator.createSSRMediaProvider({
93
102
  contentId: contentId,
@@ -0,0 +1,89 @@
1
+ import { logException } from '@atlaskit/editor-common/monitoring';
2
+ import { fetchWithRetry } from '../../utils/retry';
3
+ const COMMON_HEADERS = {
4
+ 'Content-Type': 'application/json',
5
+ Accept: 'application/json'
6
+ };
7
+ const AGG_HEADERS = {
8
+ 'X-ExperimentalApi': 'confluence-agg-beta'
9
+ };
10
+ const GRAPHQL_ENDPOINT = '/gateway/api/graphql';
11
+ const JIRA_MEDIA_READ_TOKEN_MAX_TOKEN_LENGTH = 2048;
12
+ const GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_GET_JIRA_MEDIA_TOKEN';
13
+ const GET_JIRA_MEDIA_READ_TOKEN_QUERY = `query ${GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME}($issueAri: ID!, $maxTokenLength: Int!) {
14
+ jira {
15
+ issueById(id: $issueAri) {
16
+ mediaReadToken(maxTokenLength: $maxTokenLength) @optIn(to: "JiraMediaReadTokenInIssue") {
17
+ clientId
18
+ endpointUrl
19
+ tokenLifespanInSeconds
20
+ tokensWithFiles {
21
+ edges {
22
+ node {
23
+ token
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }`;
31
+ const getJiraMediaReadToken = async issueAri => {
32
+ const bodyData = {
33
+ query: GET_JIRA_MEDIA_READ_TOKEN_QUERY,
34
+ operationName: GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME,
35
+ variables: {
36
+ issueAri,
37
+ maxTokenLength: JIRA_MEDIA_READ_TOKEN_MAX_TOKEN_LENGTH
38
+ }
39
+ };
40
+ const response = await fetchWithRetry(GRAPHQL_ENDPOINT, {
41
+ method: 'POST',
42
+ headers: {
43
+ ...COMMON_HEADERS,
44
+ ...AGG_HEADERS
45
+ },
46
+ body: JSON.stringify(bodyData)
47
+ });
48
+ if (!response.ok) {
49
+ throw new Error(`Failed to get Jira media read token: ${response.statusText}`);
50
+ }
51
+ return await response.json();
52
+ };
53
+
54
+ /**
55
+ * Fetches a media read token for a Jira issue, to allow media uploaded to Jira
56
+ * to be rendered in cross-product synced block references (e.g. in Confluence).
57
+ *
58
+ * @param issueAri - the Jira issue ARI (e.g. ari:cloud:jira:{cloudId}:issue/{issueId})
59
+ * @returns TokenData with token, config (clientId + fileStoreUrl), and optional collectionId
60
+ */
61
+ export const fetchJiraMediaToken = async issueAri => {
62
+ try {
63
+ var _response$data, _response$data$jira, _response$data$jira$i, _mediaReadToken$token, _mediaReadToken$token2, _mediaReadToken$token3, _mediaReadToken$token4, _mediaReadToken$token5;
64
+ const response = await getJiraMediaReadToken(issueAri);
65
+ const mediaReadToken = (_response$data = response.data) === null || _response$data === void 0 ? void 0 : (_response$data$jira = _response$data.jira) === null || _response$data$jira === void 0 ? void 0 : (_response$data$jira$i = _response$data$jira.issueById) === null || _response$data$jira$i === void 0 ? void 0 : _response$data$jira$i.mediaReadToken;
66
+ const clientId = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : mediaReadToken.clientId;
67
+ const endpointUrl = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : mediaReadToken.endpointUrl;
68
+
69
+ // Use the first available token from tokensWithFiles, or fall back to empty string.
70
+ // A generic read token (without specific file IDs) is sufficient for rendering.
71
+ const token = (_mediaReadToken$token = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : (_mediaReadToken$token2 = mediaReadToken.tokensWithFiles) === null || _mediaReadToken$token2 === void 0 ? void 0 : (_mediaReadToken$token3 = _mediaReadToken$token2.edges) === null || _mediaReadToken$token3 === void 0 ? void 0 : (_mediaReadToken$token4 = _mediaReadToken$token3[0]) === null || _mediaReadToken$token4 === void 0 ? void 0 : (_mediaReadToken$token5 = _mediaReadToken$token4.node) === null || _mediaReadToken$token5 === void 0 ? void 0 : _mediaReadToken$token5.token) !== null && _mediaReadToken$token !== void 0 ? _mediaReadToken$token : '';
72
+ if (!clientId || !endpointUrl) {
73
+ throw new Error('Missing clientId or endpointUrl');
74
+ }
75
+ return {
76
+ config: {
77
+ clientId,
78
+ fileStoreUrl: endpointUrl
79
+ },
80
+ token
81
+ };
82
+ } catch (error) {
83
+ logException(error, {
84
+ location: 'editor-synced-block-provider/fetchJiraMediaToken'
85
+ });
86
+ const errorMsg = error instanceof Error ? error.message : String(error);
87
+ throw new Error(`Failed to get Jira media read token: ${errorMsg}`);
88
+ }
89
+ };
@@ -0,0 +1,21 @@
1
+ import { fetchMediaToken } from './confluence/fetchMediaToken';
2
+ import { fetchJiraMediaToken } from './jira/fetchMediaToken';
3
+ export const requiresCrossProductAuth = ({
4
+ hostProduct,
5
+ sourceProduct
6
+ }) => {
7
+ return !!sourceProduct && sourceProduct !== hostProduct;
8
+ };
9
+ export const fetchTokenForSourceProduct = ({
10
+ contentId,
11
+ sourceProduct
12
+ }) => {
13
+ switch (sourceProduct) {
14
+ case 'confluence-page':
15
+ return fetchMediaToken(contentId);
16
+ case 'jira-work-item':
17
+ return fetchJiraMediaToken(contentId);
18
+ default:
19
+ throw new Error(`Unsupported source product for token fetch: ${sourceProduct}`);
20
+ }
21
+ };
@@ -274,7 +274,10 @@ export class SyncedBlockProvider extends SyncBlockDataProviderInterface {
274
274
  contentProduct: sourceProduct
275
275
  };
276
276
  case 'jira-work-item':
277
- throw new Error('Jira work item source product not supported');
277
+ return {
278
+ contentId: sourceAri,
279
+ contentProduct: sourceProduct
280
+ };
278
281
  default:
279
282
  throw new Error(`${sourceProduct} source product not supported`);
280
283
  }
@@ -60,6 +60,7 @@ export class SyncBlockProviderFactoryManager {
60
60
  return providerFactory;
61
61
  }
62
62
  getSSRProviders(resourceId) {
63
+ var _syncBlock$data;
63
64
  const dataProvider = this.deps.getDataProvider();
64
65
  if (!dataProvider) {
65
66
  return null;
@@ -74,10 +75,18 @@ export class SyncBlockProviderFactoryManager {
74
75
  if (!parsedResourceId) {
75
76
  return null;
76
77
  }
77
- const {
78
+ let {
78
79
  contentId,
79
80
  product: contentProduct
80
81
  } = parsedResourceId;
82
+ const syncBlock = this.deps.getFromCache(resourceId);
83
+ if (syncBlock !== null && syncBlock !== void 0 && (_syncBlock$data = syncBlock.data) !== null && _syncBlock$data !== void 0 && _syncBlock$data.sourceAri && syncBlock.data.product) {
84
+ const parentInfo = dataProvider.retrieveSyncBlockParentInfo(syncBlock.data.sourceAri, syncBlock.data.product);
85
+ if (parentInfo) {
86
+ contentId = parentInfo.contentId;
87
+ contentProduct = parentInfo.contentProduct;
88
+ }
89
+ }
81
90
  try {
82
91
  const mediaProvider = providerCreator.createSSRMediaProvider({
83
92
  contentId,
@@ -0,0 +1,115 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
+ import { logException } from '@atlaskit/editor-common/monitoring';
7
+ import { fetchWithRetry } from '../../utils/retry';
8
+ var COMMON_HEADERS = {
9
+ 'Content-Type': 'application/json',
10
+ Accept: 'application/json'
11
+ };
12
+ var AGG_HEADERS = {
13
+ 'X-ExperimentalApi': 'confluence-agg-beta'
14
+ };
15
+ var GRAPHQL_ENDPOINT = '/gateway/api/graphql';
16
+ var JIRA_MEDIA_READ_TOKEN_MAX_TOKEN_LENGTH = 2048;
17
+ var GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_GET_JIRA_MEDIA_TOKEN';
18
+ var GET_JIRA_MEDIA_READ_TOKEN_QUERY = "query ".concat(GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME, "($issueAri: ID!, $maxTokenLength: Int!) {\n jira {\n issueById(id: $issueAri) {\n mediaReadToken(maxTokenLength: $maxTokenLength) @optIn(to: \"JiraMediaReadTokenInIssue\") {\n clientId\n endpointUrl\n tokenLifespanInSeconds\n tokensWithFiles {\n edges {\n node {\n token\n }\n }\n }\n }\n }\n }\n}");
19
+ var getJiraMediaReadToken = /*#__PURE__*/function () {
20
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(issueAri) {
21
+ var bodyData, response;
22
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
23
+ while (1) switch (_context.prev = _context.next) {
24
+ case 0:
25
+ bodyData = {
26
+ query: GET_JIRA_MEDIA_READ_TOKEN_QUERY,
27
+ operationName: GET_JIRA_MEDIA_READ_TOKEN_OPERATION_NAME,
28
+ variables: {
29
+ issueAri: issueAri,
30
+ maxTokenLength: JIRA_MEDIA_READ_TOKEN_MAX_TOKEN_LENGTH
31
+ }
32
+ };
33
+ _context.next = 3;
34
+ return fetchWithRetry(GRAPHQL_ENDPOINT, {
35
+ method: 'POST',
36
+ headers: _objectSpread(_objectSpread({}, COMMON_HEADERS), AGG_HEADERS),
37
+ body: JSON.stringify(bodyData)
38
+ });
39
+ case 3:
40
+ response = _context.sent;
41
+ if (response.ok) {
42
+ _context.next = 6;
43
+ break;
44
+ }
45
+ throw new Error("Failed to get Jira media read token: ".concat(response.statusText));
46
+ case 6:
47
+ _context.next = 8;
48
+ return response.json();
49
+ case 8:
50
+ return _context.abrupt("return", _context.sent);
51
+ case 9:
52
+ case "end":
53
+ return _context.stop();
54
+ }
55
+ }, _callee);
56
+ }));
57
+ return function getJiraMediaReadToken(_x) {
58
+ return _ref.apply(this, arguments);
59
+ };
60
+ }();
61
+
62
+ /**
63
+ * Fetches a media read token for a Jira issue, to allow media uploaded to Jira
64
+ * to be rendered in cross-product synced block references (e.g. in Confluence).
65
+ *
66
+ * @param issueAri - the Jira issue ARI (e.g. ari:cloud:jira:{cloudId}:issue/{issueId})
67
+ * @returns TokenData with token, config (clientId + fileStoreUrl), and optional collectionId
68
+ */
69
+ export var fetchJiraMediaToken = /*#__PURE__*/function () {
70
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(issueAri) {
71
+ var _response$data, _mediaReadToken$token, _mediaReadToken$token2, response, mediaReadToken, clientId, endpointUrl, token, errorMsg;
72
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
73
+ while (1) switch (_context2.prev = _context2.next) {
74
+ case 0:
75
+ _context2.prev = 0;
76
+ _context2.next = 3;
77
+ return getJiraMediaReadToken(issueAri);
78
+ case 3:
79
+ response = _context2.sent;
80
+ mediaReadToken = (_response$data = response.data) === null || _response$data === void 0 || (_response$data = _response$data.jira) === null || _response$data === void 0 || (_response$data = _response$data.issueById) === null || _response$data === void 0 ? void 0 : _response$data.mediaReadToken;
81
+ clientId = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : mediaReadToken.clientId;
82
+ endpointUrl = mediaReadToken === null || mediaReadToken === void 0 ? void 0 : mediaReadToken.endpointUrl; // Use the first available token from tokensWithFiles, or fall back to empty string.
83
+ // A generic read token (without specific file IDs) is sufficient for rendering.
84
+ token = (_mediaReadToken$token = mediaReadToken === null || mediaReadToken === void 0 || (_mediaReadToken$token2 = mediaReadToken.tokensWithFiles) === null || _mediaReadToken$token2 === void 0 || (_mediaReadToken$token2 = _mediaReadToken$token2.edges) === null || _mediaReadToken$token2 === void 0 || (_mediaReadToken$token2 = _mediaReadToken$token2[0]) === null || _mediaReadToken$token2 === void 0 || (_mediaReadToken$token2 = _mediaReadToken$token2.node) === null || _mediaReadToken$token2 === void 0 ? void 0 : _mediaReadToken$token2.token) !== null && _mediaReadToken$token !== void 0 ? _mediaReadToken$token : '';
85
+ if (!(!clientId || !endpointUrl)) {
86
+ _context2.next = 10;
87
+ break;
88
+ }
89
+ throw new Error('Missing clientId or endpointUrl');
90
+ case 10:
91
+ return _context2.abrupt("return", {
92
+ config: {
93
+ clientId: clientId,
94
+ fileStoreUrl: endpointUrl
95
+ },
96
+ token: token
97
+ });
98
+ case 13:
99
+ _context2.prev = 13;
100
+ _context2.t0 = _context2["catch"](0);
101
+ logException(_context2.t0, {
102
+ location: 'editor-synced-block-provider/fetchJiraMediaToken'
103
+ });
104
+ errorMsg = _context2.t0 instanceof Error ? _context2.t0.message : String(_context2.t0);
105
+ throw new Error("Failed to get Jira media read token: ".concat(errorMsg));
106
+ case 18:
107
+ case "end":
108
+ return _context2.stop();
109
+ }
110
+ }, _callee2, null, [[0, 13]]);
111
+ }));
112
+ return function fetchJiraMediaToken(_x2) {
113
+ return _ref2.apply(this, arguments);
114
+ };
115
+ }();
@@ -0,0 +1,19 @@
1
+ import { fetchMediaToken } from './confluence/fetchMediaToken';
2
+ import { fetchJiraMediaToken } from './jira/fetchMediaToken';
3
+ export var requiresCrossProductAuth = function requiresCrossProductAuth(_ref) {
4
+ var hostProduct = _ref.hostProduct,
5
+ sourceProduct = _ref.sourceProduct;
6
+ return !!sourceProduct && sourceProduct !== hostProduct;
7
+ };
8
+ export var fetchTokenForSourceProduct = function fetchTokenForSourceProduct(_ref2) {
9
+ var contentId = _ref2.contentId,
10
+ sourceProduct = _ref2.sourceProduct;
11
+ switch (sourceProduct) {
12
+ case 'confluence-page':
13
+ return fetchMediaToken(contentId);
14
+ case 'jira-work-item':
15
+ return fetchJiraMediaToken(contentId);
16
+ default:
17
+ throw new Error("Unsupported source product for token fetch: ".concat(sourceProduct));
18
+ }
19
+ };
@@ -425,7 +425,10 @@ export var SyncedBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
425
425
  contentProduct: sourceProduct
426
426
  };
427
427
  case 'jira-work-item':
428
- throw new Error('Jira work item source product not supported');
428
+ return {
429
+ contentId: sourceAri,
430
+ contentProduct: sourceProduct
431
+ };
429
432
  default:
430
433
  throw new Error("".concat(sourceProduct, " source product not supported"));
431
434
  }
@@ -66,6 +66,7 @@ export var SyncBlockProviderFactoryManager = /*#__PURE__*/function () {
66
66
  }, {
67
67
  key: "getSSRProviders",
68
68
  value: function getSSRProviders(resourceId) {
69
+ var _syncBlock$data;
69
70
  var dataProvider = this.deps.getDataProvider();
70
71
  if (!dataProvider) {
71
72
  return null;
@@ -81,6 +82,14 @@ export var SyncBlockProviderFactoryManager = /*#__PURE__*/function () {
81
82
  }
82
83
  var contentId = parsedResourceId.contentId,
83
84
  contentProduct = parsedResourceId.product;
85
+ var syncBlock = this.deps.getFromCache(resourceId);
86
+ if (syncBlock !== null && syncBlock !== void 0 && (_syncBlock$data = syncBlock.data) !== null && _syncBlock$data !== void 0 && _syncBlock$data.sourceAri && syncBlock.data.product) {
87
+ var parentInfo = dataProvider.retrieveSyncBlockParentInfo(syncBlock.data.sourceAri, syncBlock.data.product);
88
+ if (parentInfo) {
89
+ contentId = parentInfo.contentId;
90
+ contentProduct = parentInfo.contentProduct;
91
+ }
92
+ }
84
93
  try {
85
94
  var mediaProvider = providerCreator.createSSRMediaProvider({
86
95
  contentId: contentId,
@@ -0,0 +1,9 @@
1
+ import type { TokenData } from '../confluence/fetchMediaToken';
2
+ /**
3
+ * Fetches a media read token for a Jira issue, to allow media uploaded to Jira
4
+ * to be rendered in cross-product synced block references (e.g. in Confluence).
5
+ *
6
+ * @param issueAri - the Jira issue ARI (e.g. ari:cloud:jira:{cloudId}:issue/{issueId})
7
+ * @returns TokenData with token, config (clientId + fileStoreUrl), and optional collectionId
8
+ */
9
+ export declare const fetchJiraMediaToken: (issueAri: string) => Promise<TokenData>;
@@ -0,0 +1,10 @@
1
+ import type { SyncBlockProduct } from '../common/types';
2
+ import type { TokenData } from './confluence/fetchMediaToken';
3
+ export declare const requiresCrossProductAuth: ({ hostProduct, sourceProduct, }: {
4
+ hostProduct: SyncBlockProduct;
5
+ sourceProduct?: SyncBlockProduct;
6
+ }) => boolean;
7
+ export declare const fetchTokenForSourceProduct: ({ contentId, sourceProduct, }: {
8
+ contentId: string;
9
+ sourceProduct?: SyncBlockProduct;
10
+ }) => Promise<TokenData>;
@@ -0,0 +1,9 @@
1
+ import type { TokenData } from '../confluence/fetchMediaToken';
2
+ /**
3
+ * Fetches a media read token for a Jira issue, to allow media uploaded to Jira
4
+ * to be rendered in cross-product synced block references (e.g. in Confluence).
5
+ *
6
+ * @param issueAri - the Jira issue ARI (e.g. ari:cloud:jira:{cloudId}:issue/{issueId})
7
+ * @returns TokenData with token, config (clientId + fileStoreUrl), and optional collectionId
8
+ */
9
+ export declare const fetchJiraMediaToken: (issueAri: string) => Promise<TokenData>;
@@ -0,0 +1,10 @@
1
+ import type { SyncBlockProduct } from '../common/types';
2
+ import type { TokenData } from './confluence/fetchMediaToken';
3
+ export declare const requiresCrossProductAuth: ({ hostProduct, sourceProduct, }: {
4
+ hostProduct: SyncBlockProduct;
5
+ sourceProduct?: SyncBlockProduct;
6
+ }) => boolean;
7
+ export declare const fetchTokenForSourceProduct: ({ contentId, sourceProduct, }: {
8
+ contentId: string;
9
+ sourceProduct?: SyncBlockProduct;
10
+ }) => Promise<TokenData>;
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@atlaskit/editor-synced-block-provider/fetchJiraMediaToken",
3
+ "main": "../dist/cjs/clients/jira/fetchMediaToken.js",
4
+ "module": "../dist/esm/clients/jira/fetchMediaToken.js",
5
+ "module:es2019": "../dist/es2019/clients/jira/fetchMediaToken.js",
6
+ "sideEffects": [
7
+ "*.compiled.css"
8
+ ],
9
+ "types": "../dist/types/clients/jira/fetchMediaToken.d.ts",
10
+ "typesVersions": {
11
+ ">=4.5 <5.9": {
12
+ "*": [
13
+ "../dist/types-ts4.5/clients/jira/fetchMediaToken.d.ts"
14
+ ]
15
+ }
16
+ }
17
+ }
package/package.json CHANGED
@@ -29,7 +29,7 @@
29
29
  "@atlaskit/editor-prosemirror": "^7.3.0",
30
30
  "@atlaskit/node-data-provider": "^9.0.0",
31
31
  "@atlaskit/platform-feature-flags": "^1.1.0",
32
- "@atlaskit/tmp-editor-statsig": "^57.0.0",
32
+ "@atlaskit/tmp-editor-statsig": "^59.1.0",
33
33
  "@babel/runtime": "^7.0.0",
34
34
  "@compiled/react": "^0.20.0",
35
35
  "graphql-ws": "^5.14.2",
@@ -38,7 +38,7 @@
38
38
  "uuid": "^3.1.0"
39
39
  },
40
40
  "peerDependencies": {
41
- "@atlaskit/editor-common": "^112.19.0",
41
+ "@atlaskit/editor-common": "^112.20.0",
42
42
  "react": "^18.2.0"
43
43
  },
44
44
  "devDependencies": {
@@ -81,7 +81,7 @@
81
81
  }
82
82
  },
83
83
  "name": "@atlaskit/editor-synced-block-provider",
84
- "version": "4.4.2",
84
+ "version": "4.5.0",
85
85
  "description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
86
86
  "author": "Atlassian Pty Ltd",
87
87
  "license": "Apache-2.0",
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@atlaskit/editor-synced-block-provider/tokenRouting",
3
+ "main": "../dist/cjs/clients/tokenRouting.js",
4
+ "module": "../dist/esm/clients/tokenRouting.js",
5
+ "module:es2019": "../dist/es2019/clients/tokenRouting.js",
6
+ "sideEffects": [
7
+ "*.compiled.css"
8
+ ],
9
+ "types": "../dist/types/clients/tokenRouting.d.ts",
10
+ "typesVersions": {
11
+ ">=4.5 <5.9": {
12
+ "*": [
13
+ "../dist/types-ts4.5/clients/tokenRouting.d.ts"
14
+ ]
15
+ }
16
+ }
17
+ }