@atlaskit/util-service-support 6.2.7 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atlaskit/util-service-support
2
2
 
3
+ ## 6.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#128616](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/128616)
8
+ [`6e9df3227a504`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6e9df3227a504) -
9
+ Improve type safety of requestServiceMultipart API
10
+
11
+ ## 6.3.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#117306](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/117306)
16
+ [`d18a5954f7ca9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d18a5954f7ca9) -
17
+ Add utility function that supports multipart responses
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies
22
+
3
23
  ## 6.2.7
4
24
 
5
25
  ### Patch Changes
package/dist/cjs/index.js CHANGED
@@ -5,9 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  var _exportNames = {
8
- utils: true
8
+ utils: true,
9
+ multipartUtils: true
9
10
  };
10
- exports.utils = void 0;
11
+ exports.utils = exports.multipartUtils = void 0;
11
12
  var _types = require("./types");
12
13
  Object.keys(_types).forEach(function (key) {
13
14
  if (key === "default" || key === "__esModule") return;
@@ -33,6 +34,8 @@ Object.keys(_serviceResources).forEach(function (key) {
33
34
  });
34
35
  });
35
36
  var serviceUtils = _interopRequireWildcard(require("./serviceUtils"));
37
+ var multipartServiceUtils = _interopRequireWildcard(require("./multipartServiceUtils"));
36
38
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
37
39
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
38
- var utils = exports.utils = serviceUtils;
40
+ var utils = exports.utils = serviceUtils;
41
+ var multipartUtils = exports.multipartUtils = multipartServiceUtils;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.requestServiceMultipart = 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 _browser = require("meros/browser");
12
+ var _types = require("./types");
13
+ var _shared = require("./shared");
14
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
+ var _featureFlagsAccessed = require("@atlaskit/react-ufo/feature-flags-accessed");
16
+ var _experienceTraceIdContext = require("@atlaskit/react-ufo/experience-trace-id-context");
17
+ 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; }
18
+ 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; }
19
+ /** Copied from meros types, as there are difficulties with resolving the type in CI */
20
+
21
+ /**
22
+ * Make a request that **may** result in an HTTP multipart response from the server.
23
+ * @returns an object with a parsed JSON body OR an object with the parts from
24
+ * the HTTP multipart response.
25
+ *
26
+ * PartsType type parameter specifies the type of the response when the server response
27
+ * is multipart.
28
+ *
29
+ * BodyType specifies the type of the response when the server response is not multipart
30
+ */
31
+ var _requestServiceMultipart = exports.requestServiceMultipart = /*#__PURE__*/function () {
32
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(serviceConfig) {
33
+ var options,
34
+ url,
35
+ securityProvider,
36
+ refreshedSecurityProvider,
37
+ path,
38
+ queryParams,
39
+ requestInit,
40
+ secOptions,
41
+ requestUrl,
42
+ headers,
43
+ credentials,
44
+ TRACING_HEADER_FOR_SERVICE_UTIL,
45
+ tracingHeaderEnabled,
46
+ tracingHeaders,
47
+ requestOptions,
48
+ fetchResponse,
49
+ parts,
50
+ _args = arguments;
51
+ return _regenerator.default.wrap(function _callee$(_context) {
52
+ while (1) switch (_context.prev = _context.next) {
53
+ case 0:
54
+ options = _args.length > 1 && _args[1] !== undefined ? _args[1] : _shared.defaultRequestServiceOptions;
55
+ url = serviceConfig.url, securityProvider = serviceConfig.securityProvider, refreshedSecurityProvider = serviceConfig.refreshedSecurityProvider;
56
+ path = options.path, queryParams = options.queryParams, requestInit = options.requestInit;
57
+ secOptions = securityProvider && securityProvider();
58
+ requestUrl = (0, _shared.buildUrl)(url, path, queryParams, secOptions);
59
+ headers = (0, _shared.buildHeaders)(secOptions, requestInit && requestInit.headers);
60
+ credentials = (0, _types.buildCredentials)(secOptions); // Get tracing headers from UFO
61
+ TRACING_HEADER_FOR_SERVICE_UTIL = 'platform_collab_provider_tracingheaders';
62
+ tracingHeaderEnabled = (0, _platformFeatureFlags.fg)('platform_collab_provider_tracingheaders');
63
+ (0, _featureFlagsAccessed.addFeatureFlagAccessed)(TRACING_HEADER_FOR_SERVICE_UTIL, tracingHeaderEnabled);
64
+ tracingHeaders = {};
65
+ if (tracingHeaderEnabled) {
66
+ tracingHeaders = (0, _experienceTraceIdContext.getActiveTraceHttpRequestHeaders)(url);
67
+ }
68
+ requestOptions = _objectSpread(_objectSpread({}, requestInit), {}, {
69
+ // populate headers mainly for the collab provider however
70
+ // other components which uses this util can get the header as well.
71
+ // Those tracing headers shall not incur any issues as long as backends handle them properly
72
+ headers: _objectSpread(_objectSpread({}, headers), tracingHeaders),
73
+ credentials: credentials
74
+ });
75
+ _context.next = 15;
76
+ return fetch(requestUrl, requestOptions);
77
+ case 15:
78
+ fetchResponse = _context.sent;
79
+ _context.next = 18;
80
+ return (0, _browser.meros)(fetchResponse);
81
+ case 18:
82
+ parts = _context.sent;
83
+ if (!(fetchResponse.ok && fetchResponse.status !== 204)) {
84
+ _context.next = 28;
85
+ break;
86
+ }
87
+ if (!(parts[Symbol.asyncIterator] < 'u')) {
88
+ _context.next = 22;
89
+ break;
90
+ }
91
+ return _context.abrupt("return", {
92
+ isMultipart: true,
93
+ parts: parts
94
+ });
95
+ case 22:
96
+ _context.next = 24;
97
+ return parts.json();
98
+ case 24:
99
+ _context.t0 = _context.sent;
100
+ return _context.abrupt("return", {
101
+ isMultipart: false,
102
+ body: _context.t0
103
+ });
104
+ case 28:
105
+ if (!(fetchResponse.status === 401 && refreshedSecurityProvider)) {
106
+ _context.next = 30;
107
+ break;
108
+ }
109
+ return _context.abrupt("return", refreshedSecurityProvider().then(function (newSecOptions) {
110
+ var retryServiceConfig = {
111
+ url: url,
112
+ securityProvider: function securityProvider() {
113
+ return newSecOptions;
114
+ }
115
+ };
116
+ return _requestServiceMultipart(retryServiceConfig, options);
117
+ }));
118
+ case 30:
119
+ return _context.abrupt("return", Promise.reject({
120
+ code: fetchResponse.status,
121
+ reason: fetchResponse.statusText
122
+ }));
123
+ case 31:
124
+ case "end":
125
+ return _context.stop();
126
+ }
127
+ }, _callee);
128
+ }));
129
+ return function requestServiceMultipart(_x) {
130
+ return _ref.apply(this, arguments);
131
+ };
132
+ }();
@@ -10,74 +10,9 @@ var _experienceTraceIdContext = require("@atlaskit/react-ufo/experience-trace-id
10
10
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
11
11
  var _featureFlagsAccessed = require("@atlaskit/react-ufo/feature-flags-accessed");
12
12
  var _types = require("./types");
13
+ var _shared = require("./shared");
13
14
  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
15
  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 defaultRequestServiceOptions = {};
16
- var buildUrl = function buildUrl(baseUrl) {
17
- var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
18
- var queryParams = arguments.length > 2 ? arguments[2] : undefined;
19
- var secOptions = arguments.length > 3 ? arguments[3] : undefined;
20
- var searchParam = new URLSearchParams(
21
- // For relative urls, the URL class requires base to be set. It's ignored if a url is not relative.
22
- // Since we only care about search params it is fine to have any base url here.
23
- new URL(baseUrl, 'https://BASE_FALLBACK').search || undefined);
24
- baseUrl = baseUrl.split('?')[0];
25
- if (queryParams) {
26
- for (var key in queryParams) {
27
- if ({}.hasOwnProperty.call(queryParams, key)) {
28
- searchParam.append(key, queryParams[key]);
29
- }
30
- }
31
- }
32
- if (secOptions && secOptions.params) {
33
- for (var _key in secOptions.params) {
34
- if ({}.hasOwnProperty.call(secOptions.params, _key)) {
35
- var values = secOptions.params[_key];
36
- if (Array.isArray(values)) {
37
- for (var i = 0; i < values.length; i++) {
38
- searchParam.append(_key, values[i]);
39
- }
40
- } else {
41
- searchParam.append(_key, values);
42
- }
43
- }
44
- }
45
- }
46
- var separator = '';
47
- if (path && baseUrl.substr(-1) !== '/' && !path.startsWith('/')) {
48
- separator = '/';
49
- }
50
- var params = searchParam.toString();
51
- if (params) {
52
- params = '?' + params;
53
- }
54
- return "".concat(baseUrl).concat(separator).concat(path).concat(params);
55
- };
56
- var addToHeaders = function addToHeaders(headers, keyValues) {
57
- if (keyValues) {
58
- for (var key in keyValues) {
59
- if ({}.hasOwnProperty.call(keyValues, key)) {
60
- var values = keyValues[key];
61
- if (Array.isArray(values)) {
62
- for (var i = 0; i < values.length; i++) {
63
- headers[key] = values[i];
64
- }
65
- } else {
66
- headers[key] = values;
67
- }
68
- }
69
- }
70
- }
71
- };
72
- var buildHeaders = function buildHeaders(secOptions, extraHeaders) {
73
- var headers = {};
74
- addToHeaders(headers, extraHeaders);
75
- if (secOptions) {
76
- addToHeaders(headers, secOptions.headers);
77
- }
78
- return headers;
79
- };
80
-
81
16
  /**
82
17
  * @returns Promise containing the json response
83
18
  */
@@ -85,17 +20,17 @@ var _requestService = exports.requestService = function requestService(serviceCo
85
20
  var url = serviceConfig.url,
86
21
  securityProvider = serviceConfig.securityProvider,
87
22
  refreshedSecurityProvider = serviceConfig.refreshedSecurityProvider;
88
- var _ref = options || defaultRequestServiceOptions,
23
+ var _ref = options || _shared.defaultRequestServiceOptions,
89
24
  path = _ref.path,
90
25
  queryParams = _ref.queryParams,
91
26
  requestInit = _ref.requestInit;
92
27
  var secOptions = securityProvider && securityProvider();
93
- var requestUrl = buildUrl(url, path, queryParams, secOptions);
94
- var headers = buildHeaders(secOptions, requestInit && requestInit.headers);
28
+ var requestUrl = (0, _shared.buildUrl)(url, path, queryParams, secOptions);
29
+ var headers = (0, _shared.buildHeaders)(secOptions, requestInit && requestInit.headers);
95
30
  var credentials = (0, _types.buildCredentials)(secOptions);
96
31
  var ignoreResponsePayload = (options === null || options === void 0 ? void 0 : options.ignoreResponsePayload) || false;
97
32
 
98
- //Get tracing headers from UFO
33
+ // Get tracing headers from UFO
99
34
  var TRACING_HEADER_FOR_SERVICE_UTIL = 'platform_collab_provider_tracingheaders';
100
35
  var tracingHeaderEnabled = (0, _platformFeatureFlags.fg)('platform_collab_provider_tracingheaders');
101
36
  (0, _featureFlagsAccessed.addFeatureFlagAccessed)(TRACING_HEADER_FOR_SERVICE_UTIL, tracingHeaderEnabled);
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.defaultRequestServiceOptions = exports.buildUrl = exports.buildHeaders = void 0;
7
+ var defaultRequestServiceOptions = exports.defaultRequestServiceOptions = {};
8
+ var buildUrl = exports.buildUrl = function buildUrl(baseUrl) {
9
+ var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
10
+ var queryParams = arguments.length > 2 ? arguments[2] : undefined;
11
+ var secOptions = arguments.length > 3 ? arguments[3] : undefined;
12
+ var searchParam = new URLSearchParams(
13
+ // For relative urls, the URL class requires base to be set. It's ignored if a url is not relative.
14
+ // Since we only care about search params it is fine to have any base url here.
15
+ new URL(baseUrl, 'https://BASE_FALLBACK').search || undefined);
16
+ baseUrl = baseUrl.split('?')[0];
17
+ if (queryParams) {
18
+ for (var key in queryParams) {
19
+ if ({}.hasOwnProperty.call(queryParams, key)) {
20
+ searchParam.append(key, queryParams[key]);
21
+ }
22
+ }
23
+ }
24
+ if (secOptions && secOptions.params) {
25
+ for (var _key in secOptions.params) {
26
+ if ({}.hasOwnProperty.call(secOptions.params, _key)) {
27
+ var values = secOptions.params[_key];
28
+ if (Array.isArray(values)) {
29
+ for (var i = 0; i < values.length; i++) {
30
+ searchParam.append(_key, values[i]);
31
+ }
32
+ } else {
33
+ searchParam.append(_key, values);
34
+ }
35
+ }
36
+ }
37
+ }
38
+ var separator = '';
39
+ if (path && baseUrl.substr(-1) !== '/' && !path.startsWith('/')) {
40
+ separator = '/';
41
+ }
42
+ var params = searchParam.toString();
43
+ if (params) {
44
+ params = '?' + params;
45
+ }
46
+ return "".concat(baseUrl).concat(separator).concat(path).concat(params);
47
+ };
48
+ var addToHeaders = function addToHeaders(headers, keyValues) {
49
+ if (keyValues) {
50
+ for (var key in keyValues) {
51
+ if ({}.hasOwnProperty.call(keyValues, key)) {
52
+ var values = keyValues[key];
53
+ if (Array.isArray(values)) {
54
+ for (var i = 0; i < values.length; i++) {
55
+ headers[key] = values[i];
56
+ }
57
+ } else {
58
+ headers[key] = values;
59
+ }
60
+ }
61
+ }
62
+ }
63
+ };
64
+ var buildHeaders = exports.buildHeaders = function buildHeaders(secOptions, extraHeaders) {
65
+ var headers = {};
66
+ addToHeaders(headers, extraHeaders);
67
+ if (secOptions) {
68
+ addToHeaders(headers, secOptions.headers);
69
+ }
70
+ return headers;
71
+ };
@@ -1,4 +1,6 @@
1
1
  export * from './types';
2
2
  export * from './serviceResources';
3
3
  import * as serviceUtils from './serviceUtils';
4
- export const utils = serviceUtils;
4
+ import * as multipartServiceUtils from './multipartServiceUtils';
5
+ export const utils = serviceUtils;
6
+ export const multipartUtils = multipartServiceUtils;
@@ -0,0 +1,87 @@
1
+ import { meros } from 'meros/browser';
2
+ import { buildCredentials } from './types';
3
+ import { buildHeaders, buildUrl, defaultRequestServiceOptions } from './shared';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
5
+ import { addFeatureFlagAccessed } from '@atlaskit/react-ufo/feature-flags-accessed';
6
+ import { getActiveTraceHttpRequestHeaders } from '@atlaskit/react-ufo/experience-trace-id-context';
7
+
8
+ /** Copied from meros types, as there are difficulties with resolving the type in CI */
9
+
10
+ /**
11
+ * Make a request that **may** result in an HTTP multipart response from the server.
12
+ * @returns an object with a parsed JSON body OR an object with the parts from
13
+ * the HTTP multipart response.
14
+ *
15
+ * PartsType type parameter specifies the type of the response when the server response
16
+ * is multipart.
17
+ *
18
+ * BodyType specifies the type of the response when the server response is not multipart
19
+ */
20
+ export const requestServiceMultipart = async (serviceConfig, options = defaultRequestServiceOptions) => {
21
+ const {
22
+ url,
23
+ securityProvider,
24
+ refreshedSecurityProvider
25
+ } = serviceConfig;
26
+ const {
27
+ path,
28
+ queryParams,
29
+ requestInit
30
+ } = options;
31
+ const secOptions = securityProvider && securityProvider();
32
+ const requestUrl = buildUrl(url, path, queryParams, secOptions);
33
+ const headers = buildHeaders(secOptions, requestInit && requestInit.headers);
34
+ const credentials = buildCredentials(secOptions);
35
+
36
+ // Get tracing headers from UFO
37
+ const TRACING_HEADER_FOR_SERVICE_UTIL = 'platform_collab_provider_tracingheaders';
38
+ const tracingHeaderEnabled = fg('platform_collab_provider_tracingheaders');
39
+ addFeatureFlagAccessed(TRACING_HEADER_FOR_SERVICE_UTIL, tracingHeaderEnabled);
40
+ let tracingHeaders = {};
41
+ if (tracingHeaderEnabled) {
42
+ tracingHeaders = getActiveTraceHttpRequestHeaders(url);
43
+ }
44
+ const requestOptions = {
45
+ ...requestInit,
46
+ // populate headers mainly for the collab provider however
47
+ // other components which uses this util can get the header as well.
48
+ // Those tracing headers shall not incur any issues as long as backends handle them properly
49
+ headers: {
50
+ ...headers,
51
+ ...tracingHeaders
52
+ },
53
+ credentials
54
+ };
55
+ const fetchResponse = await fetch(requestUrl, requestOptions);
56
+ const parts = await meros(fetchResponse);
57
+ if (fetchResponse.ok && fetchResponse.status !== 204) {
58
+ if (parts[Symbol.asyncIterator] < 'u') {
59
+ // this lets us know that the response is multipart
60
+ //
61
+ // ((parts as PartsGenerator)[Symbol.asyncIterator] as any) < 'u' came from the `meros` docs:
62
+ // https://github.com/maraisr/meros/blob/dec4feaa24090b94e8ac42fab1aff38a1e521680/readme.md
63
+ // Look for expand section `If the content-type is NOT a multipart, then meros will resolve with the response argument.`
64
+ return {
65
+ isMultipart: true,
66
+ parts: parts
67
+ };
68
+ }
69
+ return {
70
+ isMultipart: false,
71
+ body: await parts.json()
72
+ };
73
+ } else if (fetchResponse.status === 401 && refreshedSecurityProvider) {
74
+ // auth issue - try once
75
+ return refreshedSecurityProvider().then(newSecOptions => {
76
+ const retryServiceConfig = {
77
+ url,
78
+ securityProvider: () => newSecOptions
79
+ };
80
+ return requestServiceMultipart(retryServiceConfig, options);
81
+ });
82
+ }
83
+ return Promise.reject({
84
+ code: fetchResponse.status,
85
+ reason: fetchResponse.statusText
86
+ });
87
+ };
@@ -2,68 +2,7 @@ import { getActiveTraceHttpRequestHeaders } from '@atlaskit/react-ufo/experience
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { addFeatureFlagAccessed } from '@atlaskit/react-ufo/feature-flags-accessed';
4
4
  import { buildCredentials } from './types';
5
- const defaultRequestServiceOptions = {};
6
- const buildUrl = (baseUrl, path = '', queryParams, secOptions) => {
7
- const searchParam = new URLSearchParams(
8
- // For relative urls, the URL class requires base to be set. It's ignored if a url is not relative.
9
- // Since we only care about search params it is fine to have any base url here.
10
- new URL(baseUrl, 'https://BASE_FALLBACK').search || undefined);
11
- baseUrl = baseUrl.split('?')[0];
12
- if (queryParams) {
13
- for (const key in queryParams) {
14
- if ({}.hasOwnProperty.call(queryParams, key)) {
15
- searchParam.append(key, queryParams[key]);
16
- }
17
- }
18
- }
19
- if (secOptions && secOptions.params) {
20
- for (const key in secOptions.params) {
21
- if ({}.hasOwnProperty.call(secOptions.params, key)) {
22
- const values = secOptions.params[key];
23
- if (Array.isArray(values)) {
24
- for (let i = 0; i < values.length; i++) {
25
- searchParam.append(key, values[i]);
26
- }
27
- } else {
28
- searchParam.append(key, values);
29
- }
30
- }
31
- }
32
- }
33
- let separator = '';
34
- if (path && baseUrl.substr(-1) !== '/' && !path.startsWith('/')) {
35
- separator = '/';
36
- }
37
- let params = searchParam.toString();
38
- if (params) {
39
- params = '?' + params;
40
- }
41
- return `${baseUrl}${separator}${path}${params}`;
42
- };
43
- const addToHeaders = (headers, keyValues) => {
44
- if (keyValues) {
45
- for (const key in keyValues) {
46
- if ({}.hasOwnProperty.call(keyValues, key)) {
47
- const values = keyValues[key];
48
- if (Array.isArray(values)) {
49
- for (let i = 0; i < values.length; i++) {
50
- headers[key] = values[i];
51
- }
52
- } else {
53
- headers[key] = values;
54
- }
55
- }
56
- }
57
- }
58
- };
59
- const buildHeaders = (secOptions, extraHeaders) => {
60
- const headers = {};
61
- addToHeaders(headers, extraHeaders);
62
- if (secOptions) {
63
- addToHeaders(headers, secOptions.headers);
64
- }
65
- return headers;
66
- };
5
+ import { defaultRequestServiceOptions, buildUrl, buildHeaders } from './shared';
67
6
 
68
7
  /**
69
8
  * @returns Promise containing the json response
@@ -85,7 +24,7 @@ export const requestService = (serviceConfig, options) => {
85
24
  const credentials = buildCredentials(secOptions);
86
25
  const ignoreResponsePayload = (options === null || options === void 0 ? void 0 : options.ignoreResponsePayload) || false;
87
26
 
88
- //Get tracing headers from UFO
27
+ // Get tracing headers from UFO
89
28
  const TRACING_HEADER_FOR_SERVICE_UTIL = 'platform_collab_provider_tracingheaders';
90
29
  const tracingHeaderEnabled = fg('platform_collab_provider_tracingheaders');
91
30
  addFeatureFlagAccessed(TRACING_HEADER_FOR_SERVICE_UTIL, tracingHeaderEnabled);
@@ -0,0 +1,62 @@
1
+ export const defaultRequestServiceOptions = {};
2
+ export const buildUrl = (baseUrl, path = '', queryParams, secOptions) => {
3
+ const searchParam = new URLSearchParams(
4
+ // For relative urls, the URL class requires base to be set. It's ignored if a url is not relative.
5
+ // Since we only care about search params it is fine to have any base url here.
6
+ new URL(baseUrl, 'https://BASE_FALLBACK').search || undefined);
7
+ baseUrl = baseUrl.split('?')[0];
8
+ if (queryParams) {
9
+ for (const key in queryParams) {
10
+ if ({}.hasOwnProperty.call(queryParams, key)) {
11
+ searchParam.append(key, queryParams[key]);
12
+ }
13
+ }
14
+ }
15
+ if (secOptions && secOptions.params) {
16
+ for (const key in secOptions.params) {
17
+ if ({}.hasOwnProperty.call(secOptions.params, key)) {
18
+ const values = secOptions.params[key];
19
+ if (Array.isArray(values)) {
20
+ for (let i = 0; i < values.length; i++) {
21
+ searchParam.append(key, values[i]);
22
+ }
23
+ } else {
24
+ searchParam.append(key, values);
25
+ }
26
+ }
27
+ }
28
+ }
29
+ let separator = '';
30
+ if (path && baseUrl.substr(-1) !== '/' && !path.startsWith('/')) {
31
+ separator = '/';
32
+ }
33
+ let params = searchParam.toString();
34
+ if (params) {
35
+ params = '?' + params;
36
+ }
37
+ return `${baseUrl}${separator}${path}${params}`;
38
+ };
39
+ const addToHeaders = (headers, keyValues) => {
40
+ if (keyValues) {
41
+ for (const key in keyValues) {
42
+ if ({}.hasOwnProperty.call(keyValues, key)) {
43
+ const values = keyValues[key];
44
+ if (Array.isArray(values)) {
45
+ for (let i = 0; i < values.length; i++) {
46
+ headers[key] = values[i];
47
+ }
48
+ } else {
49
+ headers[key] = values;
50
+ }
51
+ }
52
+ }
53
+ }
54
+ };
55
+ export const buildHeaders = (secOptions, extraHeaders) => {
56
+ const headers = {};
57
+ addToHeaders(headers, extraHeaders);
58
+ if (secOptions) {
59
+ addToHeaders(headers, secOptions.headers);
60
+ }
61
+ return headers;
62
+ };
package/dist/esm/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './types';
2
2
  export * from './serviceResources';
3
3
  import * as serviceUtils from './serviceUtils';
4
- export var utils = serviceUtils;
4
+ import * as multipartServiceUtils from './multipartServiceUtils';
5
+ export var utils = serviceUtils;
6
+ export var multipartUtils = multipartServiceUtils;
@@ -0,0 +1,127 @@
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 { meros } from 'meros/browser';
7
+ import { buildCredentials } from './types';
8
+ import { buildHeaders, buildUrl, defaultRequestServiceOptions } from './shared';
9
+ import { fg } from '@atlaskit/platform-feature-flags';
10
+ import { addFeatureFlagAccessed } from '@atlaskit/react-ufo/feature-flags-accessed';
11
+ import { getActiveTraceHttpRequestHeaders } from '@atlaskit/react-ufo/experience-trace-id-context';
12
+
13
+ /** Copied from meros types, as there are difficulties with resolving the type in CI */
14
+
15
+ /**
16
+ * Make a request that **may** result in an HTTP multipart response from the server.
17
+ * @returns an object with a parsed JSON body OR an object with the parts from
18
+ * the HTTP multipart response.
19
+ *
20
+ * PartsType type parameter specifies the type of the response when the server response
21
+ * is multipart.
22
+ *
23
+ * BodyType specifies the type of the response when the server response is not multipart
24
+ */
25
+ var _requestServiceMultipart = /*#__PURE__*/function () {
26
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(serviceConfig) {
27
+ var options,
28
+ url,
29
+ securityProvider,
30
+ refreshedSecurityProvider,
31
+ path,
32
+ queryParams,
33
+ requestInit,
34
+ secOptions,
35
+ requestUrl,
36
+ headers,
37
+ credentials,
38
+ TRACING_HEADER_FOR_SERVICE_UTIL,
39
+ tracingHeaderEnabled,
40
+ tracingHeaders,
41
+ requestOptions,
42
+ fetchResponse,
43
+ parts,
44
+ _args = arguments;
45
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
46
+ while (1) switch (_context.prev = _context.next) {
47
+ case 0:
48
+ options = _args.length > 1 && _args[1] !== undefined ? _args[1] : defaultRequestServiceOptions;
49
+ url = serviceConfig.url, securityProvider = serviceConfig.securityProvider, refreshedSecurityProvider = serviceConfig.refreshedSecurityProvider;
50
+ path = options.path, queryParams = options.queryParams, requestInit = options.requestInit;
51
+ secOptions = securityProvider && securityProvider();
52
+ requestUrl = buildUrl(url, path, queryParams, secOptions);
53
+ headers = buildHeaders(secOptions, requestInit && requestInit.headers);
54
+ credentials = buildCredentials(secOptions); // Get tracing headers from UFO
55
+ TRACING_HEADER_FOR_SERVICE_UTIL = 'platform_collab_provider_tracingheaders';
56
+ tracingHeaderEnabled = fg('platform_collab_provider_tracingheaders');
57
+ addFeatureFlagAccessed(TRACING_HEADER_FOR_SERVICE_UTIL, tracingHeaderEnabled);
58
+ tracingHeaders = {};
59
+ if (tracingHeaderEnabled) {
60
+ tracingHeaders = getActiveTraceHttpRequestHeaders(url);
61
+ }
62
+ requestOptions = _objectSpread(_objectSpread({}, requestInit), {}, {
63
+ // populate headers mainly for the collab provider however
64
+ // other components which uses this util can get the header as well.
65
+ // Those tracing headers shall not incur any issues as long as backends handle them properly
66
+ headers: _objectSpread(_objectSpread({}, headers), tracingHeaders),
67
+ credentials: credentials
68
+ });
69
+ _context.next = 15;
70
+ return fetch(requestUrl, requestOptions);
71
+ case 15:
72
+ fetchResponse = _context.sent;
73
+ _context.next = 18;
74
+ return meros(fetchResponse);
75
+ case 18:
76
+ parts = _context.sent;
77
+ if (!(fetchResponse.ok && fetchResponse.status !== 204)) {
78
+ _context.next = 28;
79
+ break;
80
+ }
81
+ if (!(parts[Symbol.asyncIterator] < 'u')) {
82
+ _context.next = 22;
83
+ break;
84
+ }
85
+ return _context.abrupt("return", {
86
+ isMultipart: true,
87
+ parts: parts
88
+ });
89
+ case 22:
90
+ _context.next = 24;
91
+ return parts.json();
92
+ case 24:
93
+ _context.t0 = _context.sent;
94
+ return _context.abrupt("return", {
95
+ isMultipart: false,
96
+ body: _context.t0
97
+ });
98
+ case 28:
99
+ if (!(fetchResponse.status === 401 && refreshedSecurityProvider)) {
100
+ _context.next = 30;
101
+ break;
102
+ }
103
+ return _context.abrupt("return", refreshedSecurityProvider().then(function (newSecOptions) {
104
+ var retryServiceConfig = {
105
+ url: url,
106
+ securityProvider: function securityProvider() {
107
+ return newSecOptions;
108
+ }
109
+ };
110
+ return _requestServiceMultipart(retryServiceConfig, options);
111
+ }));
112
+ case 30:
113
+ return _context.abrupt("return", Promise.reject({
114
+ code: fetchResponse.status,
115
+ reason: fetchResponse.statusText
116
+ }));
117
+ case 31:
118
+ case "end":
119
+ return _context.stop();
120
+ }
121
+ }, _callee);
122
+ }));
123
+ return function requestServiceMultipart(_x) {
124
+ return _ref.apply(this, arguments);
125
+ };
126
+ }();
127
+ export { _requestServiceMultipart as requestServiceMultipart };
@@ -5,71 +5,7 @@ import { getActiveTraceHttpRequestHeaders } from '@atlaskit/react-ufo/experience
5
5
  import { fg } from '@atlaskit/platform-feature-flags';
6
6
  import { addFeatureFlagAccessed } from '@atlaskit/react-ufo/feature-flags-accessed';
7
7
  import { buildCredentials } from './types';
8
- var defaultRequestServiceOptions = {};
9
- var buildUrl = function buildUrl(baseUrl) {
10
- var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
11
- var queryParams = arguments.length > 2 ? arguments[2] : undefined;
12
- var secOptions = arguments.length > 3 ? arguments[3] : undefined;
13
- var searchParam = new URLSearchParams(
14
- // For relative urls, the URL class requires base to be set. It's ignored if a url is not relative.
15
- // Since we only care about search params it is fine to have any base url here.
16
- new URL(baseUrl, 'https://BASE_FALLBACK').search || undefined);
17
- baseUrl = baseUrl.split('?')[0];
18
- if (queryParams) {
19
- for (var key in queryParams) {
20
- if ({}.hasOwnProperty.call(queryParams, key)) {
21
- searchParam.append(key, queryParams[key]);
22
- }
23
- }
24
- }
25
- if (secOptions && secOptions.params) {
26
- for (var _key in secOptions.params) {
27
- if ({}.hasOwnProperty.call(secOptions.params, _key)) {
28
- var values = secOptions.params[_key];
29
- if (Array.isArray(values)) {
30
- for (var i = 0; i < values.length; i++) {
31
- searchParam.append(_key, values[i]);
32
- }
33
- } else {
34
- searchParam.append(_key, values);
35
- }
36
- }
37
- }
38
- }
39
- var separator = '';
40
- if (path && baseUrl.substr(-1) !== '/' && !path.startsWith('/')) {
41
- separator = '/';
42
- }
43
- var params = searchParam.toString();
44
- if (params) {
45
- params = '?' + params;
46
- }
47
- return "".concat(baseUrl).concat(separator).concat(path).concat(params);
48
- };
49
- var addToHeaders = function addToHeaders(headers, keyValues) {
50
- if (keyValues) {
51
- for (var key in keyValues) {
52
- if ({}.hasOwnProperty.call(keyValues, key)) {
53
- var values = keyValues[key];
54
- if (Array.isArray(values)) {
55
- for (var i = 0; i < values.length; i++) {
56
- headers[key] = values[i];
57
- }
58
- } else {
59
- headers[key] = values;
60
- }
61
- }
62
- }
63
- }
64
- };
65
- var buildHeaders = function buildHeaders(secOptions, extraHeaders) {
66
- var headers = {};
67
- addToHeaders(headers, extraHeaders);
68
- if (secOptions) {
69
- addToHeaders(headers, secOptions.headers);
70
- }
71
- return headers;
72
- };
8
+ import { defaultRequestServiceOptions, buildUrl, buildHeaders } from './shared';
73
9
 
74
10
  /**
75
11
  * @returns Promise containing the json response
@@ -88,7 +24,7 @@ var _requestService = function requestService(serviceConfig, options) {
88
24
  var credentials = buildCredentials(secOptions);
89
25
  var ignoreResponsePayload = (options === null || options === void 0 ? void 0 : options.ignoreResponsePayload) || false;
90
26
 
91
- //Get tracing headers from UFO
27
+ // Get tracing headers from UFO
92
28
  var TRACING_HEADER_FOR_SERVICE_UTIL = 'platform_collab_provider_tracingheaders';
93
29
  var tracingHeaderEnabled = fg('platform_collab_provider_tracingheaders');
94
30
  addFeatureFlagAccessed(TRACING_HEADER_FOR_SERVICE_UTIL, tracingHeaderEnabled);
@@ -0,0 +1,65 @@
1
+ export var defaultRequestServiceOptions = {};
2
+ export var buildUrl = function buildUrl(baseUrl) {
3
+ var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
4
+ var queryParams = arguments.length > 2 ? arguments[2] : undefined;
5
+ var secOptions = arguments.length > 3 ? arguments[3] : undefined;
6
+ var searchParam = new URLSearchParams(
7
+ // For relative urls, the URL class requires base to be set. It's ignored if a url is not relative.
8
+ // Since we only care about search params it is fine to have any base url here.
9
+ new URL(baseUrl, 'https://BASE_FALLBACK').search || undefined);
10
+ baseUrl = baseUrl.split('?')[0];
11
+ if (queryParams) {
12
+ for (var key in queryParams) {
13
+ if ({}.hasOwnProperty.call(queryParams, key)) {
14
+ searchParam.append(key, queryParams[key]);
15
+ }
16
+ }
17
+ }
18
+ if (secOptions && secOptions.params) {
19
+ for (var _key in secOptions.params) {
20
+ if ({}.hasOwnProperty.call(secOptions.params, _key)) {
21
+ var values = secOptions.params[_key];
22
+ if (Array.isArray(values)) {
23
+ for (var i = 0; i < values.length; i++) {
24
+ searchParam.append(_key, values[i]);
25
+ }
26
+ } else {
27
+ searchParam.append(_key, values);
28
+ }
29
+ }
30
+ }
31
+ }
32
+ var separator = '';
33
+ if (path && baseUrl.substr(-1) !== '/' && !path.startsWith('/')) {
34
+ separator = '/';
35
+ }
36
+ var params = searchParam.toString();
37
+ if (params) {
38
+ params = '?' + params;
39
+ }
40
+ return "".concat(baseUrl).concat(separator).concat(path).concat(params);
41
+ };
42
+ var addToHeaders = function addToHeaders(headers, keyValues) {
43
+ if (keyValues) {
44
+ for (var key in keyValues) {
45
+ if ({}.hasOwnProperty.call(keyValues, key)) {
46
+ var values = keyValues[key];
47
+ if (Array.isArray(values)) {
48
+ for (var i = 0; i < values.length; i++) {
49
+ headers[key] = values[i];
50
+ }
51
+ } else {
52
+ headers[key] = values;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ };
58
+ export var buildHeaders = function buildHeaders(secOptions, extraHeaders) {
59
+ var headers = {};
60
+ addToHeaders(headers, extraHeaders);
61
+ if (secOptions) {
62
+ addToHeaders(headers, secOptions.headers);
63
+ }
64
+ return headers;
65
+ };
@@ -1,4 +1,7 @@
1
1
  export * from './types';
2
2
  export * from './serviceResources';
3
3
  import * as serviceUtils from './serviceUtils';
4
+ import * as multipartServiceUtils from './multipartServiceUtils';
4
5
  export declare const utils: typeof serviceUtils;
6
+ export declare const multipartUtils: typeof multipartServiceUtils;
7
+ export type { RequestServiceResult, PartsGenerator, MultiPartFetchResult, BodyResult, } from './multipartServiceUtils';
@@ -0,0 +1,34 @@
1
+ import { type RequestServiceOptions, type ServiceConfig } from './types';
2
+ export type PartsGenerator<PartsType> = AsyncGenerator<Part<PartsType, unknown>>;
3
+ export type MultiPartFetchResult<PartsType> = {
4
+ isMultipart: true;
5
+ parts: PartsGenerator<PartsType>;
6
+ };
7
+ export type BodyResult<T> = {
8
+ isMultipart: false;
9
+ body: T;
10
+ };
11
+ export type RequestServiceResult<PartsType, BodyType> = MultiPartFetchResult<PartsType> | BodyResult<BodyType>;
12
+ /** Copied from meros types, as there are difficulties with resolving the type in CI */
13
+ export type Part<Body, Fallback> = {
14
+ json: false;
15
+ headers: Record<string, string>;
16
+ body: Fallback;
17
+ } | {
18
+ json: true;
19
+ headers: Record<string, string>;
20
+ body: Body;
21
+ };
22
+ type Options = Omit<RequestServiceOptions, 'ignoreResponsePayload'>;
23
+ /**
24
+ * Make a request that **may** result in an HTTP multipart response from the server.
25
+ * @returns an object with a parsed JSON body OR an object with the parts from
26
+ * the HTTP multipart response.
27
+ *
28
+ * PartsType type parameter specifies the type of the response when the server response
29
+ * is multipart.
30
+ *
31
+ * BodyType specifies the type of the response when the server response is not multipart
32
+ */
33
+ export declare const requestServiceMultipart: <PartsType, BodyType>(serviceConfig: ServiceConfig, options?: Options) => Promise<RequestServiceResult<PartsType, BodyType>>;
34
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { RequestServiceOptions, KeyValues, SecurityOptions } from './types';
2
+ export declare const defaultRequestServiceOptions: RequestServiceOptions;
3
+ export declare const buildUrl: (baseUrl: string, path?: string, queryParams?: KeyValues, secOptions?: SecurityOptions) => string;
4
+ export declare const buildHeaders: (secOptions?: SecurityOptions, extraHeaders?: KeyValues) => KeyValues;
@@ -1,4 +1,7 @@
1
1
  export * from './types';
2
2
  export * from './serviceResources';
3
3
  import * as serviceUtils from './serviceUtils';
4
+ import * as multipartServiceUtils from './multipartServiceUtils';
4
5
  export declare const utils: typeof serviceUtils;
6
+ export declare const multipartUtils: typeof multipartServiceUtils;
7
+ export type { RequestServiceResult, PartsGenerator, MultiPartFetchResult, BodyResult, } from './multipartServiceUtils';
@@ -0,0 +1,34 @@
1
+ import { type RequestServiceOptions, type ServiceConfig } from './types';
2
+ export type PartsGenerator<PartsType> = AsyncGenerator<Part<PartsType, unknown>>;
3
+ export type MultiPartFetchResult<PartsType> = {
4
+ isMultipart: true;
5
+ parts: PartsGenerator<PartsType>;
6
+ };
7
+ export type BodyResult<T> = {
8
+ isMultipart: false;
9
+ body: T;
10
+ };
11
+ export type RequestServiceResult<PartsType, BodyType> = MultiPartFetchResult<PartsType> | BodyResult<BodyType>;
12
+ /** Copied from meros types, as there are difficulties with resolving the type in CI */
13
+ export type Part<Body, Fallback> = {
14
+ json: false;
15
+ headers: Record<string, string>;
16
+ body: Fallback;
17
+ } | {
18
+ json: true;
19
+ headers: Record<string, string>;
20
+ body: Body;
21
+ };
22
+ type Options = Omit<RequestServiceOptions, 'ignoreResponsePayload'>;
23
+ /**
24
+ * Make a request that **may** result in an HTTP multipart response from the server.
25
+ * @returns an object with a parsed JSON body OR an object with the parts from
26
+ * the HTTP multipart response.
27
+ *
28
+ * PartsType type parameter specifies the type of the response when the server response
29
+ * is multipart.
30
+ *
31
+ * BodyType specifies the type of the response when the server response is not multipart
32
+ */
33
+ export declare const requestServiceMultipart: <PartsType, BodyType>(serviceConfig: ServiceConfig, options?: Options) => Promise<RequestServiceResult<PartsType, BodyType>>;
34
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { RequestServiceOptions, KeyValues, SecurityOptions } from './types';
2
+ export declare const defaultRequestServiceOptions: RequestServiceOptions;
3
+ export declare const buildUrl: (baseUrl: string, path?: string, queryParams?: KeyValues, secOptions?: SecurityOptions) => string;
4
+ export declare const buildHeaders: (secOptions?: SecurityOptions, extraHeaders?: KeyValues) => KeyValues;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/util-service-support",
3
- "version": "6.2.7",
3
+ "version": "6.3.1",
4
4
  "description": "A library of support classes for integrating React components with REST HTTP services",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -35,8 +35,9 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@atlaskit/platform-feature-flags": "^1.1.0",
38
- "@atlaskit/react-ufo": "^3.0.0",
39
- "@babel/runtime": "^7.0.0"
38
+ "@atlaskit/react-ufo": "^3.4.0",
39
+ "@babel/runtime": "^7.0.0",
40
+ "meros": "^1.3.0"
40
41
  },
41
42
  "devDependencies": {
42
43
  "es6-promise": "^4.0.5",