@atlaskit/editor-synced-block-provider 4.4.3 → 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 +12 -0
- package/dist/cjs/clients/jira/fetchMediaToken.js +122 -0
- package/dist/cjs/clients/tokenRouting.js +25 -0
- package/dist/cjs/providers/syncBlockProvider.js +4 -1
- package/dist/cjs/store-manager/syncBlockProviderFactoryManager.js +9 -0
- package/dist/es2019/clients/jira/fetchMediaToken.js +89 -0
- package/dist/es2019/clients/tokenRouting.js +21 -0
- package/dist/es2019/providers/syncBlockProvider.js +4 -1
- package/dist/es2019/store-manager/syncBlockProviderFactoryManager.js +10 -1
- package/dist/esm/clients/jira/fetchMediaToken.js +115 -0
- package/dist/esm/clients/tokenRouting.js +19 -0
- package/dist/esm/providers/syncBlockProvider.js +4 -1
- package/dist/esm/store-manager/syncBlockProviderFactoryManager.js +9 -0
- package/dist/types/clients/jira/fetchMediaToken.d.ts +9 -0
- package/dist/types/clients/tokenRouting.d.ts +10 -0
- package/dist/types-ts4.5/clients/jira/fetchMediaToken.d.ts +9 -0
- package/dist/types-ts4.5/clients/tokenRouting.d.ts +10 -0
- package/fetchJiraMediaToken/package.json +17 -0
- package/package.json +3 -3
- package/tokenRouting/package.json +17 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
3
15
|
## 4.4.3
|
|
4
16
|
|
|
5
17
|
### 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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": "^
|
|
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.
|
|
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.
|
|
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
|
+
}
|