@atlaskit/editor-card-provider 1.0.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.
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.Transformer = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
+ var Transformer = /*#__PURE__*/function () {
11
+ function Transformer() {
12
+ (0, _classCallCheck2.default)(this, Transformer);
13
+ }
14
+ (0, _createClass2.default)(Transformer, [{
15
+ key: "buildInlineAdf",
16
+ value: function buildInlineAdf(url) {
17
+ return {
18
+ type: 'inlineCard',
19
+ attrs: {
20
+ url: url
21
+ }
22
+ };
23
+ }
24
+ }, {
25
+ key: "buildBlockAdf",
26
+ value: function buildBlockAdf(url) {
27
+ return {
28
+ type: 'blockCard',
29
+ attrs: {
30
+ url: url
31
+ }
32
+ };
33
+ }
34
+ }, {
35
+ key: "buildEmbedAdf",
36
+ value: function buildEmbedAdf(url) {
37
+ return {
38
+ type: 'embedCard',
39
+ attrs: {
40
+ url: url,
41
+ layout: 'wide'
42
+ }
43
+ };
44
+ }
45
+ }, {
46
+ key: "toAdf",
47
+ value: function toAdf(url, appearance) {
48
+ switch (appearance) {
49
+ case 'inline':
50
+ return this.buildInlineAdf(url);
51
+ case 'block':
52
+ return this.buildBlockAdf(url);
53
+ case 'embed':
54
+ return this.buildEmbedAdf(url);
55
+ }
56
+ }
57
+ }]);
58
+ return Transformer;
59
+ }();
60
+ exports.Transformer = Transformer;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getStatus = void 0;
7
+ var getStatus = function getStatus(_ref) {
8
+ var meta = _ref.meta;
9
+ var access = meta.access,
10
+ visibility = meta.visibility;
11
+ switch (access) {
12
+ case 'forbidden':
13
+ if (visibility === 'not_found') {
14
+ return 'not_found';
15
+ } else {
16
+ return 'forbidden';
17
+ }
18
+ case 'unauthorized':
19
+ return 'unauthorized';
20
+ default:
21
+ return 'resolved';
22
+ }
23
+ };
24
+ exports.getStatus = getStatus;
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@atlaskit/editor-card-provider",
3
+ "version": "1.0.0",
4
+ "sideEffects": false
5
+ }
@@ -0,0 +1,37 @@
1
+ const ALLOWED_RESPONSE_STATUS_CODES = [200, 401, 404];
2
+ export class NetworkError extends Error {
3
+ constructor(error) {
4
+ super(error);
5
+ }
6
+ }
7
+
8
+ // NOTE: This is copied from @atlaskit/link-provider as we are in the middle of a deprecation.
9
+ // To read more, see https://hello.atlassian.net/browse/ENGHEALTH-661
10
+ // Also: https://product-fabric.atlassian.net/browse/EDM-5755
11
+ export async function request(method, url, data, headers) {
12
+ const requestConfig = {
13
+ method,
14
+ credentials: 'include',
15
+ headers: {
16
+ Accept: 'application/json',
17
+ 'Cache-Control': 'no-cache',
18
+ 'Content-Type': 'application/json',
19
+ ...headers
20
+ },
21
+ ...(data ? {
22
+ body: JSON.stringify(data)
23
+ } : {})
24
+ };
25
+ try {
26
+ const response = await fetch(url, requestConfig);
27
+ if (response.ok || ALLOWED_RESPONSE_STATUS_CODES.includes(response.status)) {
28
+ return await response.json();
29
+ }
30
+ throw response;
31
+ } catch (error) {
32
+ if (typeof error === 'string' || error instanceof TypeError) {
33
+ throw new NetworkError(error);
34
+ }
35
+ throw error;
36
+ }
37
+ }
@@ -0,0 +1,36 @@
1
+ // NOTE: This is copied from @atlaskit/link-provider.
2
+ // This should be moved into @atlaskit/linking-common, to be done in
3
+ // https://product-fabric.atlassian.net/browse/EDM-6042
4
+ const devBaseUrl = 'https://api-private.dev.atlassian.com';
5
+ const stgBaseUrl = 'https://pug.jira-dev.com/gateway/api';
6
+ const prodBaseUrl = 'https://api-private.atlassian.com';
7
+ export const BaseUrls = {
8
+ dev: devBaseUrl,
9
+ development: devBaseUrl,
10
+ stg: stgBaseUrl,
11
+ staging: stgBaseUrl,
12
+ prd: prodBaseUrl,
13
+ prod: prodBaseUrl,
14
+ production: prodBaseUrl
15
+ };
16
+ export const getBaseUrl = envKey => {
17
+ // If an environment is provided, then use Stargate.
18
+ if (envKey) {
19
+ return envKey in BaseUrls ? BaseUrls[envKey] : prodBaseUrl;
20
+ }
21
+
22
+ // Otherwise, use the current origin of the page.
23
+ return window.location.origin;
24
+ };
25
+ export const getResolverUrl = (envKey, baseUrlOverride) => {
26
+ // If an environment is provided, then use Stargate directly for requests.
27
+ if (envKey || baseUrlOverride) {
28
+ const baseUrl = baseUrlOverride || getBaseUrl(envKey);
29
+ return `${baseUrl}/object-resolver`;
30
+ } else {
31
+ // Otherwise, we fallback to using the Edge Proxy to access Stargate,
32
+ // which fixes some cookie issues with strict Browser policies.
33
+ return '/gateway/api/object-resolver';
34
+ }
35
+ };
36
+ export default BaseUrls;
@@ -0,0 +1 @@
1
+ export { EditorCardProvider, editorCardProvider } from './provider';
@@ -0,0 +1,182 @@
1
+ // import setimmediate to temporary fix dataloader 2.0.0 bug
2
+ // @see https://github.com/graphql/dataloader/issues/249
3
+ import 'setimmediate';
4
+ import DataLoader from 'dataloader';
5
+ import { extractPreview } from '@atlaskit/linking-common';
6
+ import { Transformer } from './transformer';
7
+ import { getBaseUrl, getResolverUrl } from './environments';
8
+ import { getStatus } from './utils';
9
+ import { CardClient } from '@atlaskit/link-provider';
10
+ import * as api from './api';
11
+ const BATCH_WAIT_TIME = 50;
12
+ const isJiraRoadMap = url => url.match(/^https:\/\/.*?\/jira\/software\/(c\/)?projects\/[^\/]+?\/boards\/.*?\/roadmap\/?/);
13
+ const isPolarisView = url => url.match(/^https:\/\/.*?\/jira\/polaris\/projects\/[^\/]+?\/ideas\/view\/\d+$|^https:\/\/.*?\/secure\/JiraProductDiscoveryAnonymous\.jspa\?hash=\w+|^https:\/\/.*?\/jira\/polaris\/share\/\w+/);
14
+ const isJwmView = url => url.match(/^https:\/\/.*?\/jira\/core\/projects\/[^\/]+?\/(timeline|calendar|list|board|summary|(form\/[^\/]+?))\/?/);
15
+ const isGiphyMedia = url => url.match(/^https:\/\/(.*?\.)?giphy\.com\/(gifs|media|clips)\//);
16
+ const isProformaView = url => url.match(/^https:\/\/[^/]+\/jira\/(core|software(\/c)?|servicedesk)\/projects\/\w+\/forms\/form\/direct\/\d+\/\d+.*$/);
17
+ export class EditorCardProvider {
18
+ constructor(envKey, baseUrlOverride) {
19
+ this.baseUrl = baseUrlOverride || getBaseUrl(envKey);
20
+ this.resolverUrl = getResolverUrl(envKey, baseUrlOverride);
21
+ this.transformer = new Transformer();
22
+ this.requestHeaders = {
23
+ Origin: this.baseUrl
24
+ };
25
+ this.providersLoader = new DataLoader(keys => this.batchProviders(keys), {
26
+ batchScheduleFn: callback => setTimeout(callback, BATCH_WAIT_TIME)
27
+ });
28
+ this.cardClient = new CardClient(envKey, baseUrlOverride);
29
+ }
30
+ async batchProviders(keys) {
31
+ // EDM-2205: Batch requests in the case that user paste multiple links at
32
+ // once. This is so that only one /providersData is being called.
33
+ const providersData = await this.fetchProvidersData();
34
+ return keys.map(() => providersData);
35
+ }
36
+ async check(resourceUrl) {
37
+ try {
38
+ const response = await this.cardClient.fetchData(resourceUrl);
39
+ if (getStatus(response) !== 'not_found') {
40
+ return true;
41
+ }
42
+ } catch (e) {
43
+ return false;
44
+ }
45
+ }
46
+ async fetchProvidersData() {
47
+ const endpoint = `${this.resolverUrl}/providers`;
48
+ const response = await api.request('post', endpoint, undefined, this.requestHeaders);
49
+ return {
50
+ patterns: response.providers.reduce((allSources, provider) => {
51
+ return allSources.concat(provider.patterns);
52
+ }, []),
53
+ userPreferences: response.userPreferences
54
+ };
55
+ }
56
+ async loadProviderData() {
57
+ try {
58
+ this.providersData = await this.providersLoader.load('providersData');
59
+ } catch (err) {
60
+ // eslint-disable-next-line
61
+ console.error('failed to fetch /providers', err);
62
+ this.providersLoader.clear('providerData');
63
+ return undefined;
64
+ }
65
+ }
66
+ async findPattern(url) {
67
+ return !!(await this.findPatternData(url)) || !!(await this.check(url));
68
+ }
69
+ doesUrlMatchPath(path, url) {
70
+ // Using [a-zA-Z0-9] here instead of \w since that includes underscores
71
+ const startingRegex = new RegExp(/^[a-zA-Z0-9]/).test(path) ? '(^|[^a-zA-Z0-9])' : '';
72
+ const endingRegex = new RegExp(/[a-zA-Z0-9]$/).test(path) ? '($|[^a-zA-Z0-9])' : '';
73
+ const escapedPath = path.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
74
+ const regexPattern = new RegExp(`${startingRegex}${escapedPath}${endingRegex}`);
75
+ return regexPattern.test(url);
76
+ }
77
+ async findUserPreference(url) {
78
+ var _this$providersData;
79
+ if (!this.providersData) {
80
+ await this.loadProviderData();
81
+ }
82
+ const userPreferences = (_this$providersData = this.providersData) === null || _this$providersData === void 0 ? void 0 : _this$providersData.userPreferences;
83
+ if (userPreferences) {
84
+ const {
85
+ defaultAppearance,
86
+ appearances
87
+ } = userPreferences;
88
+ const allMatchedLabeledAppearances = appearances.filter(({
89
+ urlSegment
90
+ }) => this.doesUrlMatchPath(urlSegment, url));
91
+ if (allMatchedLabeledAppearances.length > 0) {
92
+ const longestMatchedLabeledAppearance = allMatchedLabeledAppearances.reduce((previousLabeledAppearance, currentLabeledAppearance) => previousLabeledAppearance.urlSegment.length > currentLabeledAppearance.urlSegment.length ? previousLabeledAppearance : currentLabeledAppearance);
93
+ return longestMatchedLabeledAppearance.appearance;
94
+ }
95
+ if (defaultAppearance !== 'inline') {
96
+ return defaultAppearance;
97
+ }
98
+ }
99
+ }
100
+ async findPatternData(url) {
101
+ var _this$providersData2;
102
+ if (!this.providersData) {
103
+ await this.loadProviderData();
104
+ }
105
+ return (_this$providersData2 = this.providersData) === null || _this$providersData2 === void 0 ? void 0 : _this$providersData2.patterns.find(pattern => url.match(pattern.source));
106
+ }
107
+ getHardCodedAppearance(url) {
108
+ if (isJiraRoadMap(url) || isPolarisView(url) || isJwmView(url) || isGiphyMedia(url) || isProformaView(url)) {
109
+ return 'embed';
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Make a /resolve call and find out if result has embed capability
115
+ * @param url
116
+ * @private
117
+ */
118
+ async canBeResolvedAsEmbed(url) {
119
+ try {
120
+ const details = await this.cardClient.fetchData(url);
121
+ const data = details && details.data;
122
+ if (!data) {
123
+ return false;
124
+ }
125
+ // Imagine response is "unauthorized". We won't be able to tell if even after auth
126
+ // page going to have preview. Yes, we can show auth view for embed. But what if even after
127
+ // success auth flow there won't be preview? We will already have ugly embed ADF.
128
+ // Being on a safe side - if we get anything but resolved - we decide it can't be an embed.
129
+ if (getStatus(details) !== 'resolved') {
130
+ return false;
131
+ }
132
+ const preview = extractPreview(data, 'web');
133
+ return !!preview;
134
+ } catch (e) {
135
+ return false;
136
+ }
137
+ }
138
+ async resolve(url, appearance, shouldForceAppearance) {
139
+ try {
140
+ if (shouldForceAppearance === true) {
141
+ // At this point we don't need to check pattern nor call `check` because manual change means
142
+ // this url is already supported and can be resolved. We want to ignore all other options and
143
+ // respect user's choice.
144
+ return this.transformer.toAdf(url, appearance);
145
+ }
146
+ const hardCodedAppearance = this.getHardCodedAppearance(url);
147
+ const [matchedProviderPattern, userPreference] = await Promise.all([this.findPatternData(url), this.findUserPreference(url)]);
148
+ if (shouldForceAppearance === false && userPreference === 'url') {
149
+ return Promise.reject(undefined);
150
+ }
151
+ let isSupported = !!matchedProviderPattern || (await this.check(url));
152
+ if (isSupported) {
153
+ const providerDefaultAppearance = matchedProviderPattern === null || matchedProviderPattern === void 0 ? void 0 : matchedProviderPattern.defaultView;
154
+ let preferredAppearance = shouldForceAppearance === undefined ?
155
+ // Ignore both User and provider's appearances if older editor that doesn't send shouldForceAppearance
156
+ hardCodedAppearance || appearance :
157
+ // User preferred appearance. It would be either one that has matching domain/path pattern OR
158
+ // if user's default choice is NOT "inline" (so, block or embed at this point, url was dealt with above)
159
+ userPreference ||
160
+ // If user's default choice is "inline" or user hasn't specified preferences at all,
161
+ // we check whatever one of the hardcoded providers match url (jira roadmap, polaris, etc)
162
+ hardCodedAppearance ||
163
+ // If non match, we see if this provider has default appearance for this particular regexp
164
+ providerDefaultAppearance ||
165
+ // If not, we pick what editor (or any other client) requested
166
+ appearance;
167
+ if (preferredAppearance === userPreference && userPreference === 'embed') {
168
+ const canItBeEmbed = await this.canBeResolvedAsEmbed(url);
169
+ if (!canItBeEmbed) {
170
+ preferredAppearance = 'inline';
171
+ }
172
+ }
173
+ return this.transformer.toAdf(url, preferredAppearance);
174
+ }
175
+ } catch (e) {
176
+ // eslint-disable-next-line
177
+ console.warn(`Error when trying to check Smart Card url "${url}"${e instanceof Error ? ` - ${e.name} ${e.message}` : ''}`, e);
178
+ }
179
+ return Promise.reject(undefined);
180
+ }
181
+ }
182
+ export const editorCardProvider = new EditorCardProvider();
@@ -0,0 +1,37 @@
1
+ export class Transformer {
2
+ buildInlineAdf(url) {
3
+ return {
4
+ type: 'inlineCard',
5
+ attrs: {
6
+ url
7
+ }
8
+ };
9
+ }
10
+ buildBlockAdf(url) {
11
+ return {
12
+ type: 'blockCard',
13
+ attrs: {
14
+ url
15
+ }
16
+ };
17
+ }
18
+ buildEmbedAdf(url) {
19
+ return {
20
+ type: 'embedCard',
21
+ attrs: {
22
+ url,
23
+ layout: 'wide'
24
+ }
25
+ };
26
+ }
27
+ toAdf(url, appearance) {
28
+ switch (appearance) {
29
+ case 'inline':
30
+ return this.buildInlineAdf(url);
31
+ case 'block':
32
+ return this.buildBlockAdf(url);
33
+ case 'embed':
34
+ return this.buildEmbedAdf(url);
35
+ }
36
+ }
37
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ export const getStatus = ({
2
+ meta
3
+ }) => {
4
+ const {
5
+ access,
6
+ visibility
7
+ } = meta;
8
+ switch (access) {
9
+ case 'forbidden':
10
+ if (visibility === 'not_found') {
11
+ return 'not_found';
12
+ } else {
13
+ return 'forbidden';
14
+ }
15
+ case 'unauthorized':
16
+ return 'unauthorized';
17
+ default:
18
+ return 'resolved';
19
+ }
20
+ };
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@atlaskit/editor-card-provider",
3
+ "version": "1.0.0",
4
+ "sideEffects": false
5
+ }
@@ -0,0 +1,82 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _createClass from "@babel/runtime/helpers/createClass";
4
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
5
+ import _inherits from "@babel/runtime/helpers/inherits";
6
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
7
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
8
+ import _wrapNativeSuper from "@babel/runtime/helpers/wrapNativeSuper";
9
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
10
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
11
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
12
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
13
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
14
+ var ALLOWED_RESPONSE_STATUS_CODES = [200, 401, 404];
15
+ export var NetworkError = /*#__PURE__*/function (_Error) {
16
+ _inherits(NetworkError, _Error);
17
+ var _super = _createSuper(NetworkError);
18
+ function NetworkError(error) {
19
+ _classCallCheck(this, NetworkError);
20
+ return _super.call(this, error);
21
+ }
22
+ return _createClass(NetworkError);
23
+ }( /*#__PURE__*/_wrapNativeSuper(Error));
24
+
25
+ // NOTE: This is copied from @atlaskit/link-provider as we are in the middle of a deprecation.
26
+ // To read more, see https://hello.atlassian.net/browse/ENGHEALTH-661
27
+ // Also: https://product-fabric.atlassian.net/browse/EDM-5755
28
+ export function request(_x, _x2, _x3, _x4) {
29
+ return _request.apply(this, arguments);
30
+ }
31
+ function _request() {
32
+ _request = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(method, url, data, headers) {
33
+ var requestConfig, response;
34
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
35
+ while (1) {
36
+ switch (_context.prev = _context.next) {
37
+ case 0:
38
+ requestConfig = _objectSpread({
39
+ method: method,
40
+ credentials: 'include',
41
+ headers: _objectSpread({
42
+ Accept: 'application/json',
43
+ 'Cache-Control': 'no-cache',
44
+ 'Content-Type': 'application/json'
45
+ }, headers)
46
+ }, data ? {
47
+ body: JSON.stringify(data)
48
+ } : {});
49
+ _context.prev = 1;
50
+ _context.next = 4;
51
+ return fetch(url, requestConfig);
52
+ case 4:
53
+ response = _context.sent;
54
+ if (!(response.ok || ALLOWED_RESPONSE_STATUS_CODES.includes(response.status))) {
55
+ _context.next = 9;
56
+ break;
57
+ }
58
+ _context.next = 8;
59
+ return response.json();
60
+ case 8:
61
+ return _context.abrupt("return", _context.sent);
62
+ case 9:
63
+ throw response;
64
+ case 12:
65
+ _context.prev = 12;
66
+ _context.t0 = _context["catch"](1);
67
+ if (!(typeof _context.t0 === 'string' || _context.t0 instanceof TypeError)) {
68
+ _context.next = 16;
69
+ break;
70
+ }
71
+ throw new NetworkError(_context.t0);
72
+ case 16:
73
+ throw _context.t0;
74
+ case 17:
75
+ case "end":
76
+ return _context.stop();
77
+ }
78
+ }
79
+ }, _callee, null, [[1, 12]]);
80
+ }));
81
+ return _request.apply(this, arguments);
82
+ }
@@ -0,0 +1,36 @@
1
+ // NOTE: This is copied from @atlaskit/link-provider.
2
+ // This should be moved into @atlaskit/linking-common, to be done in
3
+ // https://product-fabric.atlassian.net/browse/EDM-6042
4
+ var devBaseUrl = 'https://api-private.dev.atlassian.com';
5
+ var stgBaseUrl = 'https://pug.jira-dev.com/gateway/api';
6
+ var prodBaseUrl = 'https://api-private.atlassian.com';
7
+ export var BaseUrls = {
8
+ dev: devBaseUrl,
9
+ development: devBaseUrl,
10
+ stg: stgBaseUrl,
11
+ staging: stgBaseUrl,
12
+ prd: prodBaseUrl,
13
+ prod: prodBaseUrl,
14
+ production: prodBaseUrl
15
+ };
16
+ export var getBaseUrl = function getBaseUrl(envKey) {
17
+ // If an environment is provided, then use Stargate.
18
+ if (envKey) {
19
+ return envKey in BaseUrls ? BaseUrls[envKey] : prodBaseUrl;
20
+ }
21
+
22
+ // Otherwise, use the current origin of the page.
23
+ return window.location.origin;
24
+ };
25
+ export var getResolverUrl = function getResolverUrl(envKey, baseUrlOverride) {
26
+ // If an environment is provided, then use Stargate directly for requests.
27
+ if (envKey || baseUrlOverride) {
28
+ var baseUrl = baseUrlOverride || getBaseUrl(envKey);
29
+ return "".concat(baseUrl, "/object-resolver");
30
+ } else {
31
+ // Otherwise, we fallback to using the Edge Proxy to access Stargate,
32
+ // which fixes some cookie issues with strict Browser policies.
33
+ return '/gateway/api/object-resolver';
34
+ }
35
+ };
36
+ export default BaseUrls;
@@ -0,0 +1 @@
1
+ export { EditorCardProvider, editorCardProvider } from './provider';