@atlaskit/link-client-extension 1.9.2 → 1.11.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,27 @@
1
1
  # @atlaskit/link-client-extension
2
2
 
3
+ ## 1.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#122437](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/122437)
8
+ [`a5e13bc24add8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/a5e13bc24add8) -
9
+ Adds the executeAtomicAction function to forward a request to actions service and execute it in
10
+ useDatasourceClientExtension
11
+
12
+ ## 1.10.0
13
+
14
+ ### Minor Changes
15
+
16
+ - [#123151](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/123151)
17
+ [`15b8082f63c21`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/15b8082f63c21) -
18
+ Adds the getDatasourceActionsAndPermissions function to fetch actions and permissions in
19
+ useDatasourceClientExtension
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies
24
+
3
25
  ## 1.9.2
4
26
 
5
27
  ### 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.useDatasourceClientExtension = exports.datasourceDetailsResponsePromiseCache = exports.datasourceDataResponsePromiseCache = exports.DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = void 0;
7
+ exports.useDatasourceClientExtension = exports.datasourceDetailsResponsePromiseCache = exports.datasourceDataResponsePromiseCache = exports.datasourceActionsPermissionsPromiseCache = exports.DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = void 0;
8
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
@@ -20,23 +20,26 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
20
20
  var URL_RESPONSE_CACHE_SIZE = 50;
21
21
  var datasourceDetailsResponsePromiseCache = exports.datasourceDetailsResponsePromiseCache = new _lru_map.LRUMap(URL_RESPONSE_CACHE_SIZE);
22
22
  var datasourceDataResponsePromiseCache = exports.datasourceDataResponsePromiseCache = new _lru_map.LRUMap(URL_RESPONSE_CACHE_SIZE);
23
+ var datasourceActionsPermissionsPromiseCache = exports.datasourceActionsPermissionsPromiseCache = new _lru_map.LRUMap(URL_RESPONSE_CACHE_SIZE);
23
24
  var DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = exports.DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = 20;
24
25
  var useDatasourceClientExtension = exports.useDatasourceClientExtension = function useDatasourceClientExtension() {
25
26
  var _useSmartLinkContext = (0, _linkProvider.useSmartLinkContext)(),
26
27
  client = _useSmartLinkContext.connections.client;
27
28
  var resolverUrl = (0, _useResolverUrl.useResolverUrl)(client);
28
29
  var cachedRequest = /*#__PURE__*/function () {
29
- var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(datasourceId, data, url, lruMap, force) {
30
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(cacheKeyId, data, url, lruMap, force) {
30
31
  var _Intl;
31
32
  var cacheKeyData, cacheKey, responsePromise, headers;
32
33
  return _regenerator.default.wrap(function _callee$(_context) {
33
34
  while (1) switch (_context.prev = _context.next) {
34
35
  case 0:
35
- cacheKeyData = _objectSpread(_objectSpread({}, data), 'fields' in data ? {
36
+ cacheKeyData = _objectSpread(_objectSpread(_objectSpread({}, data), 'fields' in data ? {
36
37
  fields: (0, _toConsumableArray2.default)(data.fields || []).sort()
38
+ } : {}), 'fieldKeys' in data ? {
39
+ fieldKeys: (0, _toConsumableArray2.default)(data.fieldKeys || []).sort()
37
40
  } : {});
38
41
  cacheKey = JSON.stringify({
39
- datasourceId: datasourceId,
42
+ cacheKeyId: cacheKeyId,
40
43
  cacheKeyData: cacheKeyData
41
44
  });
42
45
  if (force) {
@@ -49,7 +52,7 @@ var useDatasourceClientExtension = exports.useDatasourceClientExtension = functi
49
52
  }
50
53
  return _context.abrupt("return", responsePromise);
51
54
  case 6:
52
- headers = (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.datasource.add-timezone-header') ? {
55
+ headers = (0, _platformFeatureFlags.fg)('platform.linking-platform.datasource.add-timezone-header') ? {
53
56
  /**
54
57
  * This header exist to enable the backend to process relative time, eg: "today", with respect to user timezone.
55
58
  * eg: used in "confluence-object-provider" to process confluence SLLV requests to filter data for relative time.
@@ -78,26 +81,25 @@ var useDatasourceClientExtension = exports.useDatasourceClientExtension = functi
78
81
  return _ref.apply(this, arguments);
79
82
  };
80
83
  }();
81
- var getDatasourceDetails = (0, _react.useCallback)( /*#__PURE__*/function () {
82
- var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(datasourceId, data) {
83
- var force,
84
- _args2 = arguments;
84
+ var uncachedRequest = /*#__PURE__*/function () {
85
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(data, url) {
86
+ var responsePromise;
85
87
  return _regenerator.default.wrap(function _callee2$(_context2) {
86
88
  while (1) switch (_context2.prev = _context2.next) {
87
89
  case 0:
88
- force = _args2.length > 2 && _args2[2] !== undefined ? _args2[2] : false;
89
- return _context2.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/details"), datasourceDetailsResponsePromiseCache, force));
90
+ responsePromise = (0, _linkingCommon.request)('post', url, data, undefined, [200, 201, 202, 203, 204]);
91
+ return _context2.abrupt("return", responsePromise);
90
92
  case 2:
91
93
  case "end":
92
94
  return _context2.stop();
93
95
  }
94
96
  }, _callee2);
95
97
  }));
96
- return function (_x6, _x7) {
98
+ return function uncachedRequest(_x6, _x7) {
97
99
  return _ref2.apply(this, arguments);
98
100
  };
99
- }(), [resolverUrl]);
100
- var getDatasourceData = (0, _react.useCallback)( /*#__PURE__*/function () {
101
+ }();
102
+ var getDatasourceDetails = (0, _react.useCallback)( /*#__PURE__*/function () {
101
103
  var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(datasourceId, data) {
102
104
  var force,
103
105
  _args3 = arguments;
@@ -105,7 +107,7 @@ var useDatasourceClientExtension = exports.useDatasourceClientExtension = functi
105
107
  while (1) switch (_context3.prev = _context3.next) {
106
108
  case 0:
107
109
  force = _args3.length > 2 && _args3[2] !== undefined ? _args3[2] : false;
108
- return _context3.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/data"), datasourceDataResponsePromiseCache, force));
110
+ return _context3.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/details"), datasourceDetailsResponsePromiseCache, force));
109
111
  case 2:
110
112
  case "end":
111
113
  return _context3.stop();
@@ -116,10 +118,74 @@ var useDatasourceClientExtension = exports.useDatasourceClientExtension = functi
116
118
  return _ref3.apply(this, arguments);
117
119
  };
118
120
  }(), [resolverUrl]);
121
+ var getDatasourceData = (0, _react.useCallback)( /*#__PURE__*/function () {
122
+ var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(datasourceId, data) {
123
+ var force,
124
+ _args4 = arguments;
125
+ return _regenerator.default.wrap(function _callee4$(_context4) {
126
+ while (1) switch (_context4.prev = _context4.next) {
127
+ case 0:
128
+ force = _args4.length > 2 && _args4[2] !== undefined ? _args4[2] : false;
129
+ return _context4.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/data"), datasourceDataResponsePromiseCache, force));
130
+ case 2:
131
+ case "end":
132
+ return _context4.stop();
133
+ }
134
+ }, _callee4);
135
+ }));
136
+ return function (_x10, _x11) {
137
+ return _ref4.apply(this, arguments);
138
+ };
139
+ }(), [resolverUrl]);
140
+ var getDatasourceActionsAndPermissions = (0, _react.useCallback)( /*#__PURE__*/function () {
141
+ var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(data) {
142
+ var force,
143
+ resolvedCacheIdKey,
144
+ _args5 = arguments;
145
+ return _regenerator.default.wrap(function _callee5$(_context5) {
146
+ while (1) switch (_context5.prev = _context5.next) {
147
+ case 0:
148
+ force = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : false;
149
+ resolvedCacheIdKey = 'datasourceId' in data ? data.datasourceId : data.integrationKey; // This is just to prevent empty string being passed up to ORS and causing issues.
150
+ if (resolvedCacheIdKey) {
151
+ _context5.next = 4;
152
+ break;
153
+ }
154
+ throw new Error('No target was supplied to retrieve actions for');
155
+ case 4:
156
+ return _context5.abrupt("return", cachedRequest(resolvedCacheIdKey, data, "".concat(resolverUrl, "/actions"), datasourceActionsPermissionsPromiseCache, force));
157
+ case 5:
158
+ case "end":
159
+ return _context5.stop();
160
+ }
161
+ }, _callee5);
162
+ }));
163
+ return function (_x12) {
164
+ return _ref5.apply(this, arguments);
165
+ };
166
+ }(), [resolverUrl]);
167
+ var executeAtomicAction = (0, _react.useCallback)( /*#__PURE__*/function () {
168
+ var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(data) {
169
+ return _regenerator.default.wrap(function _callee6$(_context6) {
170
+ while (1) switch (_context6.prev = _context6.next) {
171
+ case 0:
172
+ return _context6.abrupt("return", uncachedRequest(data, "".concat(resolverUrl, "/actions/execute")));
173
+ case 1:
174
+ case "end":
175
+ return _context6.stop();
176
+ }
177
+ }, _callee6);
178
+ }));
179
+ return function (_x13) {
180
+ return _ref6.apply(this, arguments);
181
+ };
182
+ }(), [resolverUrl]);
119
183
  return (0, _react.useMemo)(function () {
120
184
  return {
121
185
  getDatasourceDetails: getDatasourceDetails,
122
- getDatasourceData: getDatasourceData
186
+ getDatasourceData: getDatasourceData,
187
+ getDatasourceActionsAndPermissions: getDatasourceActionsAndPermissions,
188
+ executeAtomicAction: executeAtomicAction
123
189
  };
124
- }, [getDatasourceDetails, getDatasourceData]);
190
+ }, [getDatasourceDetails, getDatasourceData, getDatasourceActionsAndPermissions, executeAtomicAction]);
125
191
  };
@@ -4,8 +4,9 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.mockDatasourceDetailsResponse = exports.mockDatasourceDataResponseWithSchema = exports.mockDatasourceDataResponse = void 0;
7
+ exports.mockExecuteActionResponseFailure = exports.mockExecuteActionResponse = exports.mockDatasourceDetailsResponse = exports.mockDatasourceDataResponseWithSchema = exports.mockDatasourceDataResponse = exports.mockActionsDiscoveryResponse = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _linkingTypes = require("@atlaskit/linking-types");
9
10
  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; }
10
11
  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; }
11
12
  var mockDatasourceDataResponse = exports.mockDatasourceDataResponse = {
@@ -23,6 +24,9 @@ var mockDatasourceDataResponse = exports.mockDatasourceDataResponse = {
23
24
  data: {
24
25
  totalCount: 1234,
25
26
  items: [{
27
+ ari: {
28
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10025'
29
+ },
26
30
  id: {
27
31
  data: 'EDM-12'
28
32
  },
@@ -46,6 +50,9 @@ var mockDatasourceDataResponse = exports.mockDatasourceDataResponse = {
46
50
  }
47
51
  }
48
52
  }, {
53
+ ari: {
54
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10026'
55
+ },
49
56
  id: {
50
57
  data: 'EDM-14'
51
58
  },
@@ -69,6 +76,9 @@ var mockDatasourceDataResponse = exports.mockDatasourceDataResponse = {
69
76
  }
70
77
  }
71
78
  }, {
79
+ ari: {
80
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10027'
81
+ },
72
82
  id: {
73
83
  data: 'EDM-15'
74
84
  },
@@ -89,6 +99,9 @@ var mockDatasourceDataResponse = exports.mockDatasourceDataResponse = {
89
99
  }
90
100
  }
91
101
  }, {
102
+ ari: {
103
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10028'
104
+ },
92
105
  id: {
93
106
  data: 'EDM-16'
94
107
  },
@@ -194,4 +207,35 @@ var mockDatasourceDataResponseWithSchema = exports.mockDatasourceDataResponseWit
194
207
  properties: mockDatasourceDetailsResponse.data.schema.properties
195
208
  }
196
209
  })
197
- });
210
+ });
211
+ var mockActionsDiscoveryResponse = exports.mockActionsDiscoveryResponse = {
212
+ actions: [{
213
+ actionKey: 'atlassian:issue:update:summary',
214
+ description: 'Updates issue summary',
215
+ fieldKey: 'summary',
216
+ integrationKey: 'jira',
217
+ type: 'string'
218
+ }],
219
+ permissions: {
220
+ data: [{
221
+ ari: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10025',
222
+ fieldKey: 'summary',
223
+ isEditable: true
224
+ }, {
225
+ ari: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10030',
226
+ fieldKey: 'summary',
227
+ isEditable: true
228
+ }]
229
+ }
230
+ };
231
+ var mockExecuteActionResponse = exports.mockExecuteActionResponse = {
232
+ operationStatus: _linkingTypes.ActionOperationStatus.SUCCESS,
233
+ errors: []
234
+ };
235
+ var mockExecuteActionResponseFailure = exports.mockExecuteActionResponseFailure = {
236
+ operationStatus: _linkingTypes.ActionOperationStatus.FAILURE,
237
+ errors: [{
238
+ message: 'summary: You must specify a summary of the issue.',
239
+ code: 400
240
+ }]
241
+ };
@@ -2,11 +2,12 @@ import { useCallback, useMemo } from 'react';
2
2
  import { LRUMap } from 'lru_map';
3
3
  import { useSmartLinkContext } from '@atlaskit/link-provider';
4
4
  import { request } from '@atlaskit/linking-common';
5
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
6
6
  import { useResolverUrl } from '../use-resolver-url';
7
7
  const URL_RESPONSE_CACHE_SIZE = 50;
8
8
  export const datasourceDetailsResponsePromiseCache = new LRUMap(URL_RESPONSE_CACHE_SIZE);
9
9
  export const datasourceDataResponsePromiseCache = new LRUMap(URL_RESPONSE_CACHE_SIZE);
10
+ export const datasourceActionsPermissionsPromiseCache = new LRUMap(URL_RESPONSE_CACHE_SIZE);
10
11
  export const DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = 20;
11
12
  export const useDatasourceClientExtension = () => {
12
13
  const {
@@ -15,17 +16,20 @@ export const useDatasourceClientExtension = () => {
15
16
  }
16
17
  } = useSmartLinkContext();
17
18
  const resolverUrl = useResolverUrl(client);
18
- const cachedRequest = async (datasourceId, data, url, lruMap, force) => {
19
+ const cachedRequest = async (cacheKeyId, data, url, lruMap, force) => {
19
20
  var _Intl;
20
21
  const cacheKeyData = {
21
22
  ...data,
22
23
  // Sort fields to use cached version of response regardless of the order
23
24
  ...('fields' in data ? {
24
25
  fields: [...(data.fields || [])].sort()
26
+ } : {}),
27
+ ...('fieldKeys' in data ? {
28
+ fieldKeys: [...(data.fieldKeys || [])].sort()
25
29
  } : {})
26
30
  };
27
31
  const cacheKey = JSON.stringify({
28
- datasourceId,
32
+ cacheKeyId,
29
33
  cacheKeyData
30
34
  });
31
35
  if (force) {
@@ -35,7 +39,7 @@ export const useDatasourceClientExtension = () => {
35
39
  if (responsePromise) {
36
40
  return responsePromise;
37
41
  }
38
- const headers = getBooleanFF('platform.linking-platform.datasource.add-timezone-header') ? {
42
+ const headers = fg('platform.linking-platform.datasource.add-timezone-header') ? {
39
43
  /**
40
44
  * This header exist to enable the backend to process relative time, eg: "today", with respect to user timezone.
41
45
  * eg: used in "confluence-object-provider" to process confluence SLLV requests to filter data for relative time.
@@ -51,10 +55,25 @@ export const useDatasourceClientExtension = () => {
51
55
  throw e;
52
56
  }
53
57
  };
58
+ const uncachedRequest = async (data, url) => {
59
+ const responsePromise = request('post', url, data, undefined, [200, 201, 202, 203, 204]);
60
+ return responsePromise;
61
+ };
54
62
  const getDatasourceDetails = useCallback(async (datasourceId, data, force = false) => cachedRequest(datasourceId, data, `${resolverUrl}/datasource/${datasourceId}/fetch/details`, datasourceDetailsResponsePromiseCache, force), [resolverUrl]);
55
63
  const getDatasourceData = useCallback(async (datasourceId, data, force = false) => cachedRequest(datasourceId, data, `${resolverUrl}/datasource/${datasourceId}/fetch/data`, datasourceDataResponsePromiseCache, force), [resolverUrl]);
64
+ const getDatasourceActionsAndPermissions = useCallback(async (data, force = false) => {
65
+ const resolvedCacheIdKey = 'datasourceId' in data ? data.datasourceId : data.integrationKey;
66
+ // This is just to prevent empty string being passed up to ORS and causing issues.
67
+ if (!resolvedCacheIdKey) {
68
+ throw new Error('No target was supplied to retrieve actions for');
69
+ }
70
+ return cachedRequest(resolvedCacheIdKey, data, `${resolverUrl}/actions`, datasourceActionsPermissionsPromiseCache, force);
71
+ }, [resolverUrl]);
72
+ const executeAtomicAction = useCallback(async data => uncachedRequest(data, `${resolverUrl}/actions/execute`), [resolverUrl]);
56
73
  return useMemo(() => ({
57
74
  getDatasourceDetails,
58
- getDatasourceData
59
- }), [getDatasourceDetails, getDatasourceData]);
75
+ getDatasourceData,
76
+ getDatasourceActionsAndPermissions,
77
+ executeAtomicAction
78
+ }), [getDatasourceDetails, getDatasourceData, getDatasourceActionsAndPermissions, executeAtomicAction]);
60
79
  };
@@ -1,3 +1,4 @@
1
+ import { ActionOperationStatus } from '@atlaskit/linking-types';
1
2
  export const mockDatasourceDataResponse = {
2
3
  meta: {
3
4
  key: 'jira-object-provider',
@@ -13,6 +14,9 @@ export const mockDatasourceDataResponse = {
13
14
  data: {
14
15
  totalCount: 1234,
15
16
  items: [{
17
+ ari: {
18
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10025'
19
+ },
16
20
  id: {
17
21
  data: 'EDM-12'
18
22
  },
@@ -36,6 +40,9 @@ export const mockDatasourceDataResponse = {
36
40
  }
37
41
  }
38
42
  }, {
43
+ ari: {
44
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10026'
45
+ },
39
46
  id: {
40
47
  data: 'EDM-14'
41
48
  },
@@ -59,6 +66,9 @@ export const mockDatasourceDataResponse = {
59
66
  }
60
67
  }
61
68
  }, {
69
+ ari: {
70
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10027'
71
+ },
62
72
  id: {
63
73
  data: 'EDM-15'
64
74
  },
@@ -79,6 +89,9 @@ export const mockDatasourceDataResponse = {
79
89
  }
80
90
  }
81
91
  }, {
92
+ ari: {
93
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10028'
94
+ },
82
95
  id: {
83
96
  data: 'EDM-16'
84
97
  },
@@ -186,4 +199,35 @@ export const mockDatasourceDataResponseWithSchema = {
186
199
  properties: mockDatasourceDetailsResponse.data.schema.properties
187
200
  }
188
201
  }
202
+ };
203
+ export const mockActionsDiscoveryResponse = {
204
+ actions: [{
205
+ actionKey: 'atlassian:issue:update:summary',
206
+ description: 'Updates issue summary',
207
+ fieldKey: 'summary',
208
+ integrationKey: 'jira',
209
+ type: 'string'
210
+ }],
211
+ permissions: {
212
+ data: [{
213
+ ari: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10025',
214
+ fieldKey: 'summary',
215
+ isEditable: true
216
+ }, {
217
+ ari: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10030',
218
+ fieldKey: 'summary',
219
+ isEditable: true
220
+ }]
221
+ }
222
+ };
223
+ export const mockExecuteActionResponse = {
224
+ operationStatus: ActionOperationStatus.SUCCESS,
225
+ errors: []
226
+ };
227
+ export const mockExecuteActionResponseFailure = {
228
+ operationStatus: ActionOperationStatus.FAILURE,
229
+ errors: [{
230
+ message: 'summary: You must specify a summary of the issue.',
231
+ code: 400
232
+ }]
189
233
  };
@@ -8,28 +8,31 @@ import { useCallback, useMemo } from 'react';
8
8
  import { LRUMap } from 'lru_map';
9
9
  import { useSmartLinkContext } from '@atlaskit/link-provider';
10
10
  import { request } from '@atlaskit/linking-common';
11
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
11
+ import { fg } from '@atlaskit/platform-feature-flags';
12
12
  import { useResolverUrl } from '../use-resolver-url';
13
13
  var URL_RESPONSE_CACHE_SIZE = 50;
14
14
  export var datasourceDetailsResponsePromiseCache = new LRUMap(URL_RESPONSE_CACHE_SIZE);
15
15
  export var datasourceDataResponsePromiseCache = new LRUMap(URL_RESPONSE_CACHE_SIZE);
16
+ export var datasourceActionsPermissionsPromiseCache = new LRUMap(URL_RESPONSE_CACHE_SIZE);
16
17
  export var DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = 20;
17
18
  export var useDatasourceClientExtension = function useDatasourceClientExtension() {
18
19
  var _useSmartLinkContext = useSmartLinkContext(),
19
20
  client = _useSmartLinkContext.connections.client;
20
21
  var resolverUrl = useResolverUrl(client);
21
22
  var cachedRequest = /*#__PURE__*/function () {
22
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(datasourceId, data, url, lruMap, force) {
23
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(cacheKeyId, data, url, lruMap, force) {
23
24
  var _Intl;
24
25
  var cacheKeyData, cacheKey, responsePromise, headers;
25
26
  return _regeneratorRuntime.wrap(function _callee$(_context) {
26
27
  while (1) switch (_context.prev = _context.next) {
27
28
  case 0:
28
- cacheKeyData = _objectSpread(_objectSpread({}, data), 'fields' in data ? {
29
+ cacheKeyData = _objectSpread(_objectSpread(_objectSpread({}, data), 'fields' in data ? {
29
30
  fields: _toConsumableArray(data.fields || []).sort()
31
+ } : {}), 'fieldKeys' in data ? {
32
+ fieldKeys: _toConsumableArray(data.fieldKeys || []).sort()
30
33
  } : {});
31
34
  cacheKey = JSON.stringify({
32
- datasourceId: datasourceId,
35
+ cacheKeyId: cacheKeyId,
33
36
  cacheKeyData: cacheKeyData
34
37
  });
35
38
  if (force) {
@@ -42,7 +45,7 @@ export var useDatasourceClientExtension = function useDatasourceClientExtension(
42
45
  }
43
46
  return _context.abrupt("return", responsePromise);
44
47
  case 6:
45
- headers = getBooleanFF('platform.linking-platform.datasource.add-timezone-header') ? {
48
+ headers = fg('platform.linking-platform.datasource.add-timezone-header') ? {
46
49
  /**
47
50
  * This header exist to enable the backend to process relative time, eg: "today", with respect to user timezone.
48
51
  * eg: used in "confluence-object-provider" to process confluence SLLV requests to filter data for relative time.
@@ -71,26 +74,25 @@ export var useDatasourceClientExtension = function useDatasourceClientExtension(
71
74
  return _ref.apply(this, arguments);
72
75
  };
73
76
  }();
74
- var getDatasourceDetails = useCallback( /*#__PURE__*/function () {
75
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(datasourceId, data) {
76
- var force,
77
- _args2 = arguments;
77
+ var uncachedRequest = /*#__PURE__*/function () {
78
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(data, url) {
79
+ var responsePromise;
78
80
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
79
81
  while (1) switch (_context2.prev = _context2.next) {
80
82
  case 0:
81
- force = _args2.length > 2 && _args2[2] !== undefined ? _args2[2] : false;
82
- return _context2.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/details"), datasourceDetailsResponsePromiseCache, force));
83
+ responsePromise = request('post', url, data, undefined, [200, 201, 202, 203, 204]);
84
+ return _context2.abrupt("return", responsePromise);
83
85
  case 2:
84
86
  case "end":
85
87
  return _context2.stop();
86
88
  }
87
89
  }, _callee2);
88
90
  }));
89
- return function (_x6, _x7) {
91
+ return function uncachedRequest(_x6, _x7) {
90
92
  return _ref2.apply(this, arguments);
91
93
  };
92
- }(), [resolverUrl]);
93
- var getDatasourceData = useCallback( /*#__PURE__*/function () {
94
+ }();
95
+ var getDatasourceDetails = useCallback( /*#__PURE__*/function () {
94
96
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(datasourceId, data) {
95
97
  var force,
96
98
  _args3 = arguments;
@@ -98,7 +100,7 @@ export var useDatasourceClientExtension = function useDatasourceClientExtension(
98
100
  while (1) switch (_context3.prev = _context3.next) {
99
101
  case 0:
100
102
  force = _args3.length > 2 && _args3[2] !== undefined ? _args3[2] : false;
101
- return _context3.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/data"), datasourceDataResponsePromiseCache, force));
103
+ return _context3.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/details"), datasourceDetailsResponsePromiseCache, force));
102
104
  case 2:
103
105
  case "end":
104
106
  return _context3.stop();
@@ -109,10 +111,74 @@ export var useDatasourceClientExtension = function useDatasourceClientExtension(
109
111
  return _ref3.apply(this, arguments);
110
112
  };
111
113
  }(), [resolverUrl]);
114
+ var getDatasourceData = useCallback( /*#__PURE__*/function () {
115
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(datasourceId, data) {
116
+ var force,
117
+ _args4 = arguments;
118
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
119
+ while (1) switch (_context4.prev = _context4.next) {
120
+ case 0:
121
+ force = _args4.length > 2 && _args4[2] !== undefined ? _args4[2] : false;
122
+ return _context4.abrupt("return", cachedRequest(datasourceId, data, "".concat(resolverUrl, "/datasource/").concat(datasourceId, "/fetch/data"), datasourceDataResponsePromiseCache, force));
123
+ case 2:
124
+ case "end":
125
+ return _context4.stop();
126
+ }
127
+ }, _callee4);
128
+ }));
129
+ return function (_x10, _x11) {
130
+ return _ref4.apply(this, arguments);
131
+ };
132
+ }(), [resolverUrl]);
133
+ var getDatasourceActionsAndPermissions = useCallback( /*#__PURE__*/function () {
134
+ var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(data) {
135
+ var force,
136
+ resolvedCacheIdKey,
137
+ _args5 = arguments;
138
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
139
+ while (1) switch (_context5.prev = _context5.next) {
140
+ case 0:
141
+ force = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : false;
142
+ resolvedCacheIdKey = 'datasourceId' in data ? data.datasourceId : data.integrationKey; // This is just to prevent empty string being passed up to ORS and causing issues.
143
+ if (resolvedCacheIdKey) {
144
+ _context5.next = 4;
145
+ break;
146
+ }
147
+ throw new Error('No target was supplied to retrieve actions for');
148
+ case 4:
149
+ return _context5.abrupt("return", cachedRequest(resolvedCacheIdKey, data, "".concat(resolverUrl, "/actions"), datasourceActionsPermissionsPromiseCache, force));
150
+ case 5:
151
+ case "end":
152
+ return _context5.stop();
153
+ }
154
+ }, _callee5);
155
+ }));
156
+ return function (_x12) {
157
+ return _ref5.apply(this, arguments);
158
+ };
159
+ }(), [resolverUrl]);
160
+ var executeAtomicAction = useCallback( /*#__PURE__*/function () {
161
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(data) {
162
+ return _regeneratorRuntime.wrap(function _callee6$(_context6) {
163
+ while (1) switch (_context6.prev = _context6.next) {
164
+ case 0:
165
+ return _context6.abrupt("return", uncachedRequest(data, "".concat(resolverUrl, "/actions/execute")));
166
+ case 1:
167
+ case "end":
168
+ return _context6.stop();
169
+ }
170
+ }, _callee6);
171
+ }));
172
+ return function (_x13) {
173
+ return _ref6.apply(this, arguments);
174
+ };
175
+ }(), [resolverUrl]);
112
176
  return useMemo(function () {
113
177
  return {
114
178
  getDatasourceDetails: getDatasourceDetails,
115
- getDatasourceData: getDatasourceData
179
+ getDatasourceData: getDatasourceData,
180
+ getDatasourceActionsAndPermissions: getDatasourceActionsAndPermissions,
181
+ executeAtomicAction: executeAtomicAction
116
182
  };
117
- }, [getDatasourceDetails, getDatasourceData]);
183
+ }, [getDatasourceDetails, getDatasourceData, getDatasourceActionsAndPermissions, executeAtomicAction]);
118
184
  };
@@ -1,6 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  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; }
3
3
  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; }
4
+ import { ActionOperationStatus } from '@atlaskit/linking-types';
4
5
  export var mockDatasourceDataResponse = {
5
6
  meta: {
6
7
  key: 'jira-object-provider',
@@ -16,6 +17,9 @@ export var mockDatasourceDataResponse = {
16
17
  data: {
17
18
  totalCount: 1234,
18
19
  items: [{
20
+ ari: {
21
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10025'
22
+ },
19
23
  id: {
20
24
  data: 'EDM-12'
21
25
  },
@@ -39,6 +43,9 @@ export var mockDatasourceDataResponse = {
39
43
  }
40
44
  }
41
45
  }, {
46
+ ari: {
47
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10026'
48
+ },
42
49
  id: {
43
50
  data: 'EDM-14'
44
51
  },
@@ -62,6 +69,9 @@ export var mockDatasourceDataResponse = {
62
69
  }
63
70
  }
64
71
  }, {
72
+ ari: {
73
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10027'
74
+ },
65
75
  id: {
66
76
  data: 'EDM-15'
67
77
  },
@@ -82,6 +92,9 @@ export var mockDatasourceDataResponse = {
82
92
  }
83
93
  }
84
94
  }, {
95
+ ari: {
96
+ data: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10028'
97
+ },
85
98
  id: {
86
99
  data: 'EDM-16'
87
100
  },
@@ -187,4 +200,35 @@ export var mockDatasourceDataResponseWithSchema = _objectSpread(_objectSpread({}
187
200
  properties: mockDatasourceDetailsResponse.data.schema.properties
188
201
  }
189
202
  })
190
- });
203
+ });
204
+ export var mockActionsDiscoveryResponse = {
205
+ actions: [{
206
+ actionKey: 'atlassian:issue:update:summary',
207
+ description: 'Updates issue summary',
208
+ fieldKey: 'summary',
209
+ integrationKey: 'jira',
210
+ type: 'string'
211
+ }],
212
+ permissions: {
213
+ data: [{
214
+ ari: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10025',
215
+ fieldKey: 'summary',
216
+ isEditable: true
217
+ }, {
218
+ ari: 'ari:cloud:jira:3ac63b37-9bca-435e-9840-eff6f8739dba:issue/10030',
219
+ fieldKey: 'summary',
220
+ isEditable: true
221
+ }]
222
+ }
223
+ };
224
+ export var mockExecuteActionResponse = {
225
+ operationStatus: ActionOperationStatus.SUCCESS,
226
+ errors: []
227
+ };
228
+ export var mockExecuteActionResponseFailure = {
229
+ operationStatus: ActionOperationStatus.FAILURE,
230
+ errors: [{
231
+ message: 'summary: You must specify a summary of the issue.',
232
+ code: 400
233
+ }]
234
+ };
@@ -1,9 +1,12 @@
1
1
  import { LRUMap } from 'lru_map';
2
- import type { DatasourceDataRequest, DatasourceDataResponse, DatasourceDetailsRequest, DatasourceDetailsResponse } from '@atlaskit/linking-types';
2
+ import type { ActionsDiscoveryRequest, ActionsDiscoveryResponse, ActionsServiceDiscoveryResponse, AtomicActionExecuteRequest, AtomicActionExecuteResponse, DatasourceDataRequest, DatasourceDataResponse, DatasourceDetailsRequest, DatasourceDetailsResponse } from '@atlaskit/linking-types';
3
3
  export declare const datasourceDetailsResponsePromiseCache: LRUMap<string, Promise<DatasourceDetailsResponse>>;
4
4
  export declare const datasourceDataResponsePromiseCache: LRUMap<string, Promise<DatasourceDataResponse>>;
5
+ export declare const datasourceActionsPermissionsPromiseCache: LRUMap<string, Promise<ActionsServiceDiscoveryResponse>>;
5
6
  export declare const DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = 20;
6
7
  export declare const useDatasourceClientExtension: () => {
7
- getDatasourceDetails: (datasourceId: string, data: DatasourceDetailsRequest, force?: any) => Promise<DatasourceDetailsResponse>;
8
- getDatasourceData: (datasourceId: string, data: DatasourceDataRequest, force?: any) => Promise<DatasourceDataResponse>;
8
+ getDatasourceDetails: (datasourceId: string, data: DatasourceDetailsRequest, force?: boolean) => Promise<DatasourceDetailsResponse>;
9
+ getDatasourceData: (datasourceId: string, data: DatasourceDataRequest, force?: boolean) => Promise<DatasourceDataResponse>;
10
+ getDatasourceActionsAndPermissions: (data: ActionsDiscoveryRequest, force?: boolean) => Promise<ActionsDiscoveryResponse>;
11
+ executeAtomicAction: (data: AtomicActionExecuteRequest) => Promise<AtomicActionExecuteResponse>;
9
12
  };
@@ -1,4 +1,7 @@
1
- import type { DatasourceDataResponse, DatasourceDetailsResponse } from '@atlaskit/linking-types';
1
+ import { type ActionsDiscoveryResponse, type AtomicActionExecuteResponse, type DatasourceDataResponse, type DatasourceDetailsResponse } from '@atlaskit/linking-types';
2
2
  export declare const mockDatasourceDataResponse: DatasourceDataResponse;
3
3
  export declare const mockDatasourceDetailsResponse: DatasourceDetailsResponse;
4
4
  export declare const mockDatasourceDataResponseWithSchema: DatasourceDataResponse;
5
+ export declare const mockActionsDiscoveryResponse: ActionsDiscoveryResponse;
6
+ export declare const mockExecuteActionResponse: AtomicActionExecuteResponse;
7
+ export declare const mockExecuteActionResponseFailure: AtomicActionExecuteResponse;
@@ -1,9 +1,12 @@
1
1
  import { LRUMap } from 'lru_map';
2
- import type { DatasourceDataRequest, DatasourceDataResponse, DatasourceDetailsRequest, DatasourceDetailsResponse } from '@atlaskit/linking-types';
2
+ import type { ActionsDiscoveryRequest, ActionsDiscoveryResponse, ActionsServiceDiscoveryResponse, AtomicActionExecuteRequest, AtomicActionExecuteResponse, DatasourceDataRequest, DatasourceDataResponse, DatasourceDetailsRequest, DatasourceDetailsResponse } from '@atlaskit/linking-types';
3
3
  export declare const datasourceDetailsResponsePromiseCache: LRUMap<string, Promise<DatasourceDetailsResponse>>;
4
4
  export declare const datasourceDataResponsePromiseCache: LRUMap<string, Promise<DatasourceDataResponse>>;
5
+ export declare const datasourceActionsPermissionsPromiseCache: LRUMap<string, Promise<ActionsServiceDiscoveryResponse>>;
5
6
  export declare const DEFAULT_GET_DATASOURCE_DATA_PAGE_SIZE = 20;
6
7
  export declare const useDatasourceClientExtension: () => {
7
- getDatasourceDetails: (datasourceId: string, data: DatasourceDetailsRequest, force?: any) => Promise<DatasourceDetailsResponse>;
8
- getDatasourceData: (datasourceId: string, data: DatasourceDataRequest, force?: any) => Promise<DatasourceDataResponse>;
8
+ getDatasourceDetails: (datasourceId: string, data: DatasourceDetailsRequest, force?: boolean) => Promise<DatasourceDetailsResponse>;
9
+ getDatasourceData: (datasourceId: string, data: DatasourceDataRequest, force?: boolean) => Promise<DatasourceDataResponse>;
10
+ getDatasourceActionsAndPermissions: (data: ActionsDiscoveryRequest, force?: boolean) => Promise<ActionsDiscoveryResponse>;
11
+ executeAtomicAction: (data: AtomicActionExecuteRequest) => Promise<AtomicActionExecuteResponse>;
9
12
  };
@@ -1,4 +1,7 @@
1
- import type { DatasourceDataResponse, DatasourceDetailsResponse } from '@atlaskit/linking-types';
1
+ import { type ActionsDiscoveryResponse, type AtomicActionExecuteResponse, type DatasourceDataResponse, type DatasourceDetailsResponse } from '@atlaskit/linking-types';
2
2
  export declare const mockDatasourceDataResponse: DatasourceDataResponse;
3
3
  export declare const mockDatasourceDetailsResponse: DatasourceDetailsResponse;
4
4
  export declare const mockDatasourceDataResponseWithSchema: DatasourceDataResponse;
5
+ export declare const mockActionsDiscoveryResponse: ActionsDiscoveryResponse;
6
+ export declare const mockExecuteActionResponse: AtomicActionExecuteResponse;
7
+ export declare const mockExecuteActionResponseFailure: AtomicActionExecuteResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-client-extension",
3
- "version": "1.9.2",
3
+ "version": "1.11.0",
4
4
  "description": "Extension methods for linking platform client",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -34,19 +34,19 @@
34
34
  ".": "./src/index.ts"
35
35
  },
36
36
  "dependencies": {
37
- "@atlaskit/linking-common": "^5.7.0",
38
- "@atlaskit/linking-types": "^8.9.0",
37
+ "@atlaskit/linking-common": "^5.8.0",
38
+ "@atlaskit/linking-types": "^8.12.0",
39
39
  "@atlaskit/platform-feature-flags": "0.3.0",
40
40
  "@babel/runtime": "^7.0.0",
41
41
  "json-ld-types": "^4.1.0",
42
42
  "lru_map": "^0.4.1"
43
43
  },
44
44
  "peerDependencies": {
45
- "@atlaskit/link-provider": "^1.12.0",
45
+ "@atlaskit/link-provider": "^1.14.0",
46
46
  "react": "^16.8.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@atlassian/feature-flags-test-utils": "0.2.2",
49
+ "@atlassian/feature-flags-test-utils": "0.2.3",
50
50
  "@testing-library/react": "^12.1.5",
51
51
  "@testing-library/react-hooks": "^8.0.1",
52
52
  "react-dom": "^16.8.0",