@backstage/frontend-app-api 0.2.0-next.1 → 0.2.0-next.2
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 +22 -0
- package/dist/index.esm.js +387 -83
- package/dist/index.esm.js.map +1 -1
- package/package.json +11 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @backstage/frontend-app-api
|
|
2
2
|
|
|
3
|
+
## 0.2.0-next.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4461d87d5a: Removed support for the new `useRouteRef`.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 5072824817: Implement `toString()` and `toJSON()` for extension instances.
|
|
12
|
+
- 06432f900c: Updates for `at` -> `attachTo` refactor.
|
|
13
|
+
- 1718ec75b7: Added support for the existing routing system.
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/frontend-plugin-api@0.2.0-next.2
|
|
16
|
+
- @backstage/core-app-api@1.11.0-next.2
|
|
17
|
+
- @backstage/core-components@0.13.6-next.2
|
|
18
|
+
- @backstage/core-plugin-api@1.7.0-next.1
|
|
19
|
+
- @backstage/plugin-graphiql@0.2.55-next.2
|
|
20
|
+
- @backstage/theme@0.4.3-next.0
|
|
21
|
+
- @backstage/config@1.1.1-next.0
|
|
22
|
+
- @backstage/types@1.1.1
|
|
23
|
+
- @backstage/version-bridge@1.0.5
|
|
24
|
+
|
|
3
25
|
## 0.2.0-next.1
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/index.esm.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useMemo, useState, useEffect } from 'react';
|
|
2
2
|
import { ConfigReader } from '@backstage/config';
|
|
3
|
-
import { createExtension, createExtensionInput, coreExtensionData,
|
|
4
|
-
import { useRoutes, BrowserRouter, useInRouterContext, MemoryRouter, Route } from 'react-router-dom';
|
|
3
|
+
import { createExtension, createExtensionInput, coreExtensionData, createThemeExtension } from '@backstage/frontend-plugin-api';
|
|
4
|
+
import { useRoutes, matchRoutes, generatePath, BrowserRouter, useInRouterContext, MemoryRouter, Route } from 'react-router-dom';
|
|
5
5
|
import { SidebarPage, sidebarConfig, Sidebar, SidebarDivider, useSidebarOpenState, Link, SidebarItem, Progress, ErrorPage, ErrorPanel } from '@backstage/core-components';
|
|
6
|
+
import { useRouteRef, useApi, appThemeApiRef, FeatureFlagState, createApiFactory, discoveryApiRef, configApiRef, alertApiRef, analyticsApiRef, errorApiRef, storageApiRef, fetchApiRef, identityApiRef, oauthRequestApiRef, googleAuthApiRef, microsoftAuthApiRef, githubAuthApiRef, oktaAuthApiRef, gitlabAuthApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, atlassianAuthApiRef, attachComponentData, featureFlagsApiRef } from '@backstage/core-plugin-api';
|
|
6
7
|
import { makeStyles } from '@material-ui/core';
|
|
7
8
|
import mapValues from 'lodash/mapValues';
|
|
8
|
-
import { useApi, appThemeApiRef, FeatureFlagState, createApiFactory, discoveryApiRef, configApiRef, alertApiRef, analyticsApiRef, errorApiRef, storageApiRef, fetchApiRef, identityApiRef, oauthRequestApiRef, googleAuthApiRef, microsoftAuthApiRef, githubAuthApiRef, oktaAuthApiRef, gitlabAuthApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, atlassianAuthApiRef, attachComponentData, useRouteRef as useRouteRef$1, featureFlagsApiRef } from '@backstage/core-plugin-api';
|
|
9
9
|
import { UrlPatternDiscovery, AlertApiForwarder, NoOpAnalyticsApi, ErrorAlerter, ErrorApiForwarder, UnhandledErrorForwarder, WebStorage, createFetchApi, FetchMiddlewares, OAuthRequestManager, GoogleAuth, MicrosoftAuth, GithubAuth, OktaAuth, GitlabAuth, OneLoginAuth, BitbucketAuth, BitbucketServerAuth, AtlassianAuth, ApiFactoryRegistry, AppThemeSelector, ApiResolver, ApiProvider } from '@backstage/core-app-api';
|
|
10
10
|
import useObservable from 'react-use/lib/useObservable';
|
|
11
|
-
import { createVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';
|
|
11
|
+
import { createVersionedContext, createVersionedValueMap, getOrCreateGlobalSingleton } from '@backstage/version-bridge';
|
|
12
12
|
import { permissionApiRef, IdentityPermissionApi } from '@backstage/plugin-permission-react';
|
|
13
13
|
import Button from '@material-ui/core/Button';
|
|
14
14
|
import MuiApartmentIcon from '@material-ui/icons/Apartment';
|
|
@@ -38,7 +38,7 @@ import LightIcon from '@material-ui/icons/WbSunny';
|
|
|
38
38
|
|
|
39
39
|
const Core = createExtension({
|
|
40
40
|
id: "core",
|
|
41
|
-
|
|
41
|
+
attachTo: { id: "root", input: "default" },
|
|
42
42
|
inputs: {
|
|
43
43
|
apis: createExtensionInput({
|
|
44
44
|
api: coreExtensionData.apiFactory
|
|
@@ -51,7 +51,7 @@ const Core = createExtension({
|
|
|
51
51
|
|
|
52
52
|
const CoreRoutes = createExtension({
|
|
53
53
|
id: "core.routes",
|
|
54
|
-
|
|
54
|
+
attachTo: { id: "core.layout", input: "content" },
|
|
55
55
|
inputs: {
|
|
56
56
|
routes: createExtensionInput({
|
|
57
57
|
path: coreExtensionData.routePath,
|
|
@@ -80,7 +80,7 @@ const CoreRoutes = createExtension({
|
|
|
80
80
|
|
|
81
81
|
const CoreLayout = createExtension({
|
|
82
82
|
id: "core.layout",
|
|
83
|
-
|
|
83
|
+
attachTo: { id: "root", input: "default" },
|
|
84
84
|
inputs: {
|
|
85
85
|
nav: createExtensionInput(
|
|
86
86
|
{
|
|
@@ -182,12 +182,12 @@ const SidebarLogo = () => {
|
|
|
182
182
|
};
|
|
183
183
|
const SidebarNavItem = (props) => {
|
|
184
184
|
const { icon: Icon, title, routeRef } = props;
|
|
185
|
-
const to = useRouteRef(routeRef)();
|
|
185
|
+
const to = useRouteRef(routeRef)({});
|
|
186
186
|
return /* @__PURE__ */ React.createElement(SidebarItem, { to, icon: Icon, text: title });
|
|
187
187
|
};
|
|
188
188
|
const CoreNav = createExtension({
|
|
189
189
|
id: "core.nav",
|
|
190
|
-
|
|
190
|
+
attachTo: { id: "core.layout", input: "nav" },
|
|
191
191
|
inputs: {
|
|
192
192
|
items: createExtensionInput({
|
|
193
193
|
target: coreExtensionData.navTarget
|
|
@@ -203,6 +203,31 @@ const CoreNav = createExtension({
|
|
|
203
203
|
}
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
+
var __defProp$2 = Object.defineProperty;
|
|
207
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
208
|
+
var __publicField$2 = (obj, key, value) => {
|
|
209
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
210
|
+
return value;
|
|
211
|
+
};
|
|
212
|
+
var __accessCheck = (obj, member, msg) => {
|
|
213
|
+
if (!member.has(obj))
|
|
214
|
+
throw TypeError("Cannot " + msg);
|
|
215
|
+
};
|
|
216
|
+
var __privateGet = (obj, member, getter) => {
|
|
217
|
+
__accessCheck(obj, member, "read from private field");
|
|
218
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
219
|
+
};
|
|
220
|
+
var __privateAdd = (obj, member, value) => {
|
|
221
|
+
if (member.has(obj))
|
|
222
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
223
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
224
|
+
};
|
|
225
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
226
|
+
__accessCheck(obj, member, "write to private field");
|
|
227
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
228
|
+
return value;
|
|
229
|
+
};
|
|
230
|
+
var _extensionData;
|
|
206
231
|
function resolveInputData(dataMap, attachment, inputName) {
|
|
207
232
|
return mapValues(dataMap, (ref) => {
|
|
208
233
|
const value = attachment.getData(ref);
|
|
@@ -240,6 +265,46 @@ function resolveInputs(inputMap, attachments) {
|
|
|
240
265
|
);
|
|
241
266
|
});
|
|
242
267
|
}
|
|
268
|
+
function indent(str) {
|
|
269
|
+
return str.replace(/^/gm, " ");
|
|
270
|
+
}
|
|
271
|
+
class ExtensionInstanceImpl {
|
|
272
|
+
constructor(id, extensionData, attachments, source) {
|
|
273
|
+
__publicField$2(this, "$$type", "@backstage/ExtensionInstance");
|
|
274
|
+
__publicField$2(this, "id");
|
|
275
|
+
__privateAdd(this, _extensionData, void 0);
|
|
276
|
+
__publicField$2(this, "attachments");
|
|
277
|
+
__publicField$2(this, "source");
|
|
278
|
+
this.id = id;
|
|
279
|
+
__privateSet(this, _extensionData, extensionData);
|
|
280
|
+
this.attachments = attachments;
|
|
281
|
+
this.source = source;
|
|
282
|
+
}
|
|
283
|
+
getData(ref) {
|
|
284
|
+
return __privateGet(this, _extensionData).get(ref.id);
|
|
285
|
+
}
|
|
286
|
+
toJSON() {
|
|
287
|
+
return {
|
|
288
|
+
id: this.id,
|
|
289
|
+
output: __privateGet(this, _extensionData).size > 0 ? [...__privateGet(this, _extensionData).keys()] : void 0,
|
|
290
|
+
attachments: this.attachments.size > 0 ? Object.fromEntries(this.attachments) : void 0
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
toString() {
|
|
294
|
+
const out = __privateGet(this, _extensionData).size > 0 ? ` out=[${[...__privateGet(this, _extensionData).keys()].join(", ")}]` : "";
|
|
295
|
+
if (this.attachments.size === 0) {
|
|
296
|
+
return `<${this.id}${out} />`;
|
|
297
|
+
}
|
|
298
|
+
return [
|
|
299
|
+
`<${this.id}${out}>`,
|
|
300
|
+
...[...this.attachments.entries()].map(
|
|
301
|
+
([k, v]) => indent([`${k} [`, ...v.map((e) => indent(e.toString())), `]`].join("\n"))
|
|
302
|
+
),
|
|
303
|
+
`</${this.id}>`
|
|
304
|
+
].join("\n");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
_extensionData = new WeakMap();
|
|
243
308
|
function createExtensionInstance(options) {
|
|
244
309
|
var _a;
|
|
245
310
|
const { extension, config, source, attachments } = options;
|
|
@@ -277,17 +342,15 @@ function createExtensionInstance(options) {
|
|
|
277
342
|
`Failed to instantiate extension '${extension.id}'${e.name === "Error" ? `, ${e.message}` : `; caused by ${e}`}`
|
|
278
343
|
);
|
|
279
344
|
}
|
|
280
|
-
return
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
attachments
|
|
287
|
-
};
|
|
345
|
+
return new ExtensionInstanceImpl(
|
|
346
|
+
options.extension.id,
|
|
347
|
+
extensionData,
|
|
348
|
+
attachments,
|
|
349
|
+
source
|
|
350
|
+
);
|
|
288
351
|
}
|
|
289
352
|
|
|
290
|
-
const knownExtensionParameters = ["
|
|
353
|
+
const knownExtensionParameters = ["attachTo", "disabled", "config"];
|
|
291
354
|
function readAppExtensionParameters(rootConfig) {
|
|
292
355
|
const arr = rootConfig.getOptional("app.extensions");
|
|
293
356
|
if (!Array.isArray(arr)) {
|
|
@@ -353,14 +416,28 @@ function expandShorthandExtensionParameters(arrayEntry, arrayIndex) {
|
|
|
353
416
|
if (typeof value !== "object" || Array.isArray(value)) {
|
|
354
417
|
throw new Error(errorMsg("value must be a boolean or object", id));
|
|
355
418
|
}
|
|
356
|
-
const
|
|
419
|
+
const attachTo = value.attachTo;
|
|
357
420
|
const disabled = value.disabled;
|
|
358
421
|
const config = value.config;
|
|
359
|
-
if (
|
|
360
|
-
|
|
361
|
-
|
|
422
|
+
if (attachTo !== void 0) {
|
|
423
|
+
if (attachTo === null || typeof attachTo !== "object" || Array.isArray(attachTo)) {
|
|
424
|
+
throw new Error(errorMsg("must be an object", id, "attachTo"));
|
|
425
|
+
}
|
|
426
|
+
if (typeof attachTo.id !== "string" || attachTo.id === "") {
|
|
427
|
+
throw new Error(
|
|
428
|
+
errorMsg("must be a non-empty string", id, "attachTo.id")
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
if (typeof attachTo.input !== "string" || attachTo.input === "") {
|
|
432
|
+
throw new Error(
|
|
433
|
+
errorMsg("must be a non-empty string", id, "attachTo.input")
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (disabled !== void 0 && typeof disabled !== "boolean") {
|
|
362
438
|
throw new Error(errorMsg("must be a boolean", id, "disabled"));
|
|
363
|
-
}
|
|
439
|
+
}
|
|
440
|
+
if (config !== void 0 && (typeof config !== "object" || config === null || Array.isArray(config))) {
|
|
364
441
|
throw new Error(errorMsg("must be an object", id, "config"));
|
|
365
442
|
}
|
|
366
443
|
const unknownKeys = Object.keys(value).filter(
|
|
@@ -379,7 +456,7 @@ function expandShorthandExtensionParameters(arrayEntry, arrayIndex) {
|
|
|
379
456
|
}
|
|
380
457
|
return {
|
|
381
458
|
id,
|
|
382
|
-
|
|
459
|
+
attachTo,
|
|
383
460
|
disabled,
|
|
384
461
|
config
|
|
385
462
|
};
|
|
@@ -402,7 +479,7 @@ function mergeExtensionParameters(options) {
|
|
|
402
479
|
extension,
|
|
403
480
|
params: {
|
|
404
481
|
source,
|
|
405
|
-
|
|
482
|
+
attachTo: extension.attachTo,
|
|
406
483
|
disabled: extension.disabled,
|
|
407
484
|
config: void 0
|
|
408
485
|
}
|
|
@@ -411,7 +488,7 @@ function mergeExtensionParameters(options) {
|
|
|
411
488
|
extension,
|
|
412
489
|
params: {
|
|
413
490
|
source: void 0,
|
|
414
|
-
|
|
491
|
+
attachTo: extension.attachTo,
|
|
415
492
|
disabled: extension.disabled,
|
|
416
493
|
config: void 0
|
|
417
494
|
}
|
|
@@ -456,8 +533,8 @@ function mergeExtensionParameters(options) {
|
|
|
456
533
|
);
|
|
457
534
|
if (existingIndex !== -1) {
|
|
458
535
|
const existing = overrides[existingIndex];
|
|
459
|
-
if (overrideParam.
|
|
460
|
-
existing.params.
|
|
536
|
+
if (overrideParam.attachTo) {
|
|
537
|
+
existing.params.attachTo = overrideParam.attachTo;
|
|
461
538
|
}
|
|
462
539
|
if (overrideParam.config) {
|
|
463
540
|
existing.params.config = overrideParam.config;
|
|
@@ -475,31 +552,12 @@ function mergeExtensionParameters(options) {
|
|
|
475
552
|
}
|
|
476
553
|
return overrides.filter((override) => !override.params.disabled).map((param) => ({
|
|
477
554
|
extension: param.extension,
|
|
478
|
-
|
|
555
|
+
attachTo: param.params.attachTo,
|
|
479
556
|
source: param.params.source,
|
|
480
557
|
config: param.params.config
|
|
481
558
|
}));
|
|
482
559
|
}
|
|
483
560
|
|
|
484
|
-
const RoutingContext = createContext({
|
|
485
|
-
resolve: () => () => ""
|
|
486
|
-
});
|
|
487
|
-
class RouteResolver {
|
|
488
|
-
constructor(routePaths) {
|
|
489
|
-
this.routePaths = routePaths;
|
|
490
|
-
}
|
|
491
|
-
resolve(anyRouteRef) {
|
|
492
|
-
const basePath = this.routePaths.get(anyRouteRef);
|
|
493
|
-
if (!basePath) {
|
|
494
|
-
return void 0;
|
|
495
|
-
}
|
|
496
|
-
return () => basePath;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
function RoutingProvider(props) {
|
|
500
|
-
return /* @__PURE__ */ React.createElement(RoutingContext.Provider, { value: new RouteResolver(props.routePaths) }, props.children);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
561
|
function getAvailablePlugins() {
|
|
504
562
|
var _a;
|
|
505
563
|
const discovered = window["__@backstage/discovered__"];
|
|
@@ -817,6 +875,179 @@ function overrideBaseUrlConfigs(inputConfigs) {
|
|
|
817
875
|
return configs;
|
|
818
876
|
}
|
|
819
877
|
|
|
878
|
+
const routeRefType = getOrCreateGlobalSingleton(
|
|
879
|
+
"route-ref-type",
|
|
880
|
+
() => Symbol("route-ref-type")
|
|
881
|
+
);
|
|
882
|
+
function isRouteRef(routeRef) {
|
|
883
|
+
return routeRef[routeRefType] === "absolute";
|
|
884
|
+
}
|
|
885
|
+
function isSubRouteRef(routeRef) {
|
|
886
|
+
return routeRef[routeRefType] === "sub";
|
|
887
|
+
}
|
|
888
|
+
function isExternalRouteRef(routeRef) {
|
|
889
|
+
return routeRef[routeRefType] === "external";
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
function joinPaths$1(...paths) {
|
|
893
|
+
const normalized = paths.join("/").replace(/\/\/+/g, "/");
|
|
894
|
+
if (normalized !== "/" && normalized.endsWith("/")) {
|
|
895
|
+
return normalized.slice(0, -1);
|
|
896
|
+
}
|
|
897
|
+
return normalized;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function resolveTargetRef(anyRouteRef, routePaths, routeBindings) {
|
|
901
|
+
let targetRef;
|
|
902
|
+
let subRoutePath = "";
|
|
903
|
+
if (isRouteRef(anyRouteRef)) {
|
|
904
|
+
targetRef = anyRouteRef;
|
|
905
|
+
} else if (isSubRouteRef(anyRouteRef)) {
|
|
906
|
+
targetRef = anyRouteRef.parent;
|
|
907
|
+
subRoutePath = anyRouteRef.path;
|
|
908
|
+
} else if (isExternalRouteRef(anyRouteRef)) {
|
|
909
|
+
const resolvedRoute = routeBindings.get(anyRouteRef);
|
|
910
|
+
if (!resolvedRoute) {
|
|
911
|
+
return [void 0, ""];
|
|
912
|
+
}
|
|
913
|
+
if (isRouteRef(resolvedRoute)) {
|
|
914
|
+
targetRef = resolvedRoute;
|
|
915
|
+
} else if (isSubRouteRef(resolvedRoute)) {
|
|
916
|
+
targetRef = resolvedRoute.parent;
|
|
917
|
+
subRoutePath = resolvedRoute.path;
|
|
918
|
+
} else {
|
|
919
|
+
throw new Error(
|
|
920
|
+
`ExternalRouteRef was bound to invalid target, ${resolvedRoute}`
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
} else if (anyRouteRef[routeRefType]) {
|
|
924
|
+
throw new Error(
|
|
925
|
+
`Unknown or invalid route ref type, ${anyRouteRef[routeRefType]}`
|
|
926
|
+
);
|
|
927
|
+
} else {
|
|
928
|
+
throw new Error(`Unknown object passed to useRouteRef, got ${anyRouteRef}`);
|
|
929
|
+
}
|
|
930
|
+
if (!targetRef) {
|
|
931
|
+
return [void 0, ""];
|
|
932
|
+
}
|
|
933
|
+
const resolvedPath = routePaths.get(targetRef);
|
|
934
|
+
if (resolvedPath === void 0) {
|
|
935
|
+
return [void 0, ""];
|
|
936
|
+
}
|
|
937
|
+
const targetPath = joinPaths$1(resolvedPath, subRoutePath);
|
|
938
|
+
return [targetRef, targetPath];
|
|
939
|
+
}
|
|
940
|
+
function resolveBasePath(targetRef, sourceLocation, routePaths, routeParents, routeObjects) {
|
|
941
|
+
var _a;
|
|
942
|
+
const match = (_a = matchRoutes(routeObjects, sourceLocation)) != null ? _a : [];
|
|
943
|
+
const refDiffList = Array();
|
|
944
|
+
let matchIndex = -1;
|
|
945
|
+
for (let targetSearchRef = targetRef; targetSearchRef; targetSearchRef = routeParents.get(targetSearchRef)) {
|
|
946
|
+
matchIndex = match.findIndex(
|
|
947
|
+
(m) => m.route.routeRefs.has(targetSearchRef)
|
|
948
|
+
);
|
|
949
|
+
if (matchIndex !== -1) {
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
refDiffList.unshift(targetSearchRef);
|
|
953
|
+
}
|
|
954
|
+
if (refDiffList.length === 0) {
|
|
955
|
+
matchIndex -= 1;
|
|
956
|
+
}
|
|
957
|
+
const parentPath = matchIndex === -1 ? "" : match[matchIndex].pathname;
|
|
958
|
+
const diffPaths = refDiffList.slice(0, -1).map((ref) => {
|
|
959
|
+
const path = routePaths.get(ref);
|
|
960
|
+
if (path === void 0) {
|
|
961
|
+
throw new Error(`No path for ${ref}`);
|
|
962
|
+
}
|
|
963
|
+
if (path.includes(":")) {
|
|
964
|
+
throw new Error(
|
|
965
|
+
`Cannot route to ${targetRef} with parent ${ref} as it has parameters`
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
return path;
|
|
969
|
+
});
|
|
970
|
+
return `${joinPaths$1(parentPath, ...diffPaths)}/`;
|
|
971
|
+
}
|
|
972
|
+
class RouteResolver {
|
|
973
|
+
constructor(routePaths, routeParents, routeObjects, routeBindings, appBasePath) {
|
|
974
|
+
this.routePaths = routePaths;
|
|
975
|
+
this.routeParents = routeParents;
|
|
976
|
+
this.routeObjects = routeObjects;
|
|
977
|
+
this.routeBindings = routeBindings;
|
|
978
|
+
this.appBasePath = appBasePath;
|
|
979
|
+
}
|
|
980
|
+
resolve(anyRouteRef, sourceLocation) {
|
|
981
|
+
const [targetRef, targetPath] = resolveTargetRef(
|
|
982
|
+
anyRouteRef,
|
|
983
|
+
this.routePaths,
|
|
984
|
+
this.routeBindings
|
|
985
|
+
);
|
|
986
|
+
if (!targetRef) {
|
|
987
|
+
return void 0;
|
|
988
|
+
}
|
|
989
|
+
let relativeSourceLocation;
|
|
990
|
+
if (typeof sourceLocation === "string") {
|
|
991
|
+
relativeSourceLocation = this.trimPath(sourceLocation);
|
|
992
|
+
} else if (sourceLocation.pathname) {
|
|
993
|
+
relativeSourceLocation = {
|
|
994
|
+
...sourceLocation,
|
|
995
|
+
pathname: this.trimPath(sourceLocation.pathname)
|
|
996
|
+
};
|
|
997
|
+
} else {
|
|
998
|
+
relativeSourceLocation = sourceLocation;
|
|
999
|
+
}
|
|
1000
|
+
const basePath = this.appBasePath + resolveBasePath(
|
|
1001
|
+
targetRef,
|
|
1002
|
+
relativeSourceLocation,
|
|
1003
|
+
this.routePaths,
|
|
1004
|
+
this.routeParents,
|
|
1005
|
+
this.routeObjects
|
|
1006
|
+
);
|
|
1007
|
+
const routeFunc = (...[params]) => {
|
|
1008
|
+
const encodedParams = params && mapValues(params, (value) => {
|
|
1009
|
+
if (typeof value === "string") {
|
|
1010
|
+
return value.replaceAll(/[&?#;\/]/g, (c) => encodeURIComponent(c));
|
|
1011
|
+
}
|
|
1012
|
+
return value;
|
|
1013
|
+
});
|
|
1014
|
+
return joinPaths$1(basePath, generatePath(targetPath, encodedParams));
|
|
1015
|
+
};
|
|
1016
|
+
return routeFunc;
|
|
1017
|
+
}
|
|
1018
|
+
trimPath(targetPath) {
|
|
1019
|
+
if (!targetPath) {
|
|
1020
|
+
return targetPath;
|
|
1021
|
+
}
|
|
1022
|
+
if (targetPath.startsWith(this.appBasePath)) {
|
|
1023
|
+
return targetPath.slice(this.appBasePath.length);
|
|
1024
|
+
}
|
|
1025
|
+
return targetPath;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
const RoutingContext = createVersionedContext(
|
|
1030
|
+
"routing-context"
|
|
1031
|
+
);
|
|
1032
|
+
const RoutingProvider = ({
|
|
1033
|
+
routePaths,
|
|
1034
|
+
routeParents,
|
|
1035
|
+
routeObjects,
|
|
1036
|
+
routeBindings,
|
|
1037
|
+
basePath = "",
|
|
1038
|
+
children
|
|
1039
|
+
}) => {
|
|
1040
|
+
const resolver = new RouteResolver(
|
|
1041
|
+
routePaths,
|
|
1042
|
+
routeParents,
|
|
1043
|
+
routeObjects,
|
|
1044
|
+
routeBindings,
|
|
1045
|
+
basePath
|
|
1046
|
+
);
|
|
1047
|
+
const versionedValue = createVersionedValueMap({ 1: resolver });
|
|
1048
|
+
return /* @__PURE__ */ React.createElement(RoutingContext.Provider, { value: versionedValue }, children);
|
|
1049
|
+
};
|
|
1050
|
+
|
|
820
1051
|
const apis = [
|
|
821
1052
|
createApiFactory({
|
|
822
1053
|
api: discoveryApiRef,
|
|
@@ -1097,6 +1328,93 @@ const DarkTheme = createThemeExtension({
|
|
|
1097
1328
|
Provider: ({ children }) => /* @__PURE__ */ React.createElement(UnifiedThemeProvider, { theme: themes.dark, children })
|
|
1098
1329
|
});
|
|
1099
1330
|
|
|
1331
|
+
const MATCH_ALL_ROUTE = {
|
|
1332
|
+
caseSensitive: false,
|
|
1333
|
+
path: "*",
|
|
1334
|
+
element: "match-all",
|
|
1335
|
+
// These elements aren't used, so we add in a bit of debug information
|
|
1336
|
+
routeRefs: /* @__PURE__ */ new Set(),
|
|
1337
|
+
plugins: /* @__PURE__ */ new Set()
|
|
1338
|
+
};
|
|
1339
|
+
function joinPaths(...paths) {
|
|
1340
|
+
const normalized = paths.join("/").replace(/\/\/+/g, "/");
|
|
1341
|
+
if (normalized !== "/" && normalized.endsWith("/")) {
|
|
1342
|
+
return normalized.slice(0, -1);
|
|
1343
|
+
}
|
|
1344
|
+
return normalized;
|
|
1345
|
+
}
|
|
1346
|
+
function extractRouteInfoFromInstanceTree(roots) {
|
|
1347
|
+
const routePaths = /* @__PURE__ */ new Map();
|
|
1348
|
+
const routeParents = /* @__PURE__ */ new Map();
|
|
1349
|
+
const routeObjects = new Array();
|
|
1350
|
+
function visit(current, collectedPath, foundRefForCollectedPath = false, parentRef, candidateParentRef, parentObj) {
|
|
1351
|
+
var _a, _b;
|
|
1352
|
+
const routePath = (_a = current.getData(coreExtensionData.routePath)) == null ? void 0 : _a.replace(/^\//, "");
|
|
1353
|
+
const routeRef = current.getData(coreExtensionData.routeRef);
|
|
1354
|
+
const parentChildren = (_b = parentObj == null ? void 0 : parentObj.children) != null ? _b : routeObjects;
|
|
1355
|
+
let currentObj = parentObj;
|
|
1356
|
+
let newCollectedPath = collectedPath;
|
|
1357
|
+
let newFoundRefForCollectedPath = foundRefForCollectedPath;
|
|
1358
|
+
let newParentRef = parentRef;
|
|
1359
|
+
let newCandidateParentRef = candidateParentRef;
|
|
1360
|
+
if (routePath !== void 0) {
|
|
1361
|
+
currentObj = {
|
|
1362
|
+
path: routePath,
|
|
1363
|
+
element: "mounted",
|
|
1364
|
+
routeRefs: /* @__PURE__ */ new Set(),
|
|
1365
|
+
caseSensitive: false,
|
|
1366
|
+
children: [MATCH_ALL_ROUTE],
|
|
1367
|
+
plugins: /* @__PURE__ */ new Set()
|
|
1368
|
+
};
|
|
1369
|
+
parentChildren.push(currentObj);
|
|
1370
|
+
newParentRef = candidateParentRef;
|
|
1371
|
+
newCandidateParentRef = void 0;
|
|
1372
|
+
if (newFoundRefForCollectedPath) {
|
|
1373
|
+
newCollectedPath = routePath;
|
|
1374
|
+
newFoundRefForCollectedPath = false;
|
|
1375
|
+
} else {
|
|
1376
|
+
newCollectedPath = collectedPath ? joinPaths(collectedPath, routePath) : routePath;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
if (routeRef) {
|
|
1380
|
+
const routeRefId = routeRef.id;
|
|
1381
|
+
if (routeRefId !== current.id) {
|
|
1382
|
+
throw new Error(
|
|
1383
|
+
`Route ref '${routeRefId}' must have the same ID as extension '${current.id}'`
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
if (!newCandidateParentRef) {
|
|
1387
|
+
newCandidateParentRef = routeRef;
|
|
1388
|
+
}
|
|
1389
|
+
if (newCollectedPath !== void 0) {
|
|
1390
|
+
routePaths.set(routeRef, newCollectedPath);
|
|
1391
|
+
newFoundRefForCollectedPath = true;
|
|
1392
|
+
}
|
|
1393
|
+
routeParents.set(routeRef, newParentRef);
|
|
1394
|
+
currentObj == null ? void 0 : currentObj.routeRefs.add(routeRef);
|
|
1395
|
+
if (current.source) {
|
|
1396
|
+
currentObj == null ? void 0 : currentObj.plugins.add(toLegacyPlugin(current.source));
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
for (const children of current.attachments.values()) {
|
|
1400
|
+
for (const child of children) {
|
|
1401
|
+
visit(
|
|
1402
|
+
child,
|
|
1403
|
+
newCollectedPath,
|
|
1404
|
+
newFoundRefForCollectedPath,
|
|
1405
|
+
newParentRef,
|
|
1406
|
+
newCandidateParentRef,
|
|
1407
|
+
currentObj
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
for (const root of roots) {
|
|
1413
|
+
visit(root);
|
|
1414
|
+
}
|
|
1415
|
+
return { routePaths, routeParents, routeObjects };
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1100
1418
|
function createExtensionTree(options) {
|
|
1101
1419
|
const plugins = getAvailablePlugins();
|
|
1102
1420
|
const { instances } = createInstances({
|
|
@@ -1128,7 +1446,7 @@ function createExtensionTree(options) {
|
|
|
1128
1446
|
},
|
|
1129
1447
|
getSidebarItems() {
|
|
1130
1448
|
const RoutedSidebarItem = (props) => {
|
|
1131
|
-
const location = useRouteRef
|
|
1449
|
+
const location = useRouteRef(props.routeRef);
|
|
1132
1450
|
return /* @__PURE__ */ React.createElement(SidebarItem, { icon: props.icon, to: location(), text: props.title });
|
|
1133
1451
|
};
|
|
1134
1452
|
return this.getExtensionAttachments("core.nav", "items").map((node, index) => {
|
|
@@ -1166,7 +1484,8 @@ function createInstances(options) {
|
|
|
1166
1484
|
});
|
|
1167
1485
|
const attachmentMap = /* @__PURE__ */ new Map();
|
|
1168
1486
|
for (const instanceParams of extensionParams) {
|
|
1169
|
-
const
|
|
1487
|
+
const extensionId = instanceParams.attachTo.id;
|
|
1488
|
+
const pointId = instanceParams.attachTo.input;
|
|
1170
1489
|
let pointMap = attachmentMap.get(extensionId);
|
|
1171
1490
|
if (!pointMap) {
|
|
1172
1491
|
pointMap = /* @__PURE__ */ new Map();
|
|
@@ -1224,7 +1543,7 @@ function createApp(options) {
|
|
|
1224
1543
|
plugins: allPlugins,
|
|
1225
1544
|
config
|
|
1226
1545
|
});
|
|
1227
|
-
const
|
|
1546
|
+
const routeInfo = extractRouteInfoFromInstanceTree(rootInstances);
|
|
1228
1547
|
const coreInstance = rootInstances.find(({ id }) => id === "core");
|
|
1229
1548
|
if (!coreInstance) {
|
|
1230
1549
|
throw Error("Unable to find core extension instance");
|
|
@@ -1232,7 +1551,9 @@ function createApp(options) {
|
|
|
1232
1551
|
const apiHolder = createApiHolder(coreInstance, config);
|
|
1233
1552
|
const appContext = createLegacyAppContext(allPlugins);
|
|
1234
1553
|
const rootElements = rootInstances.map((e) => /* @__PURE__ */ React.createElement(React.Fragment, { key: e.id }, e.getData(coreExtensionData.reactElement))).filter((x) => !!x);
|
|
1235
|
-
const App = () => /* @__PURE__ */ React.createElement(ApiProvider, { apis: apiHolder }, /* @__PURE__ */ React.createElement(AppContextProvider, { appContext }, /* @__PURE__ */ React.createElement(AppThemeProvider, null, /* @__PURE__ */ React.createElement(RoutingProvider, {
|
|
1554
|
+
const App = () => /* @__PURE__ */ React.createElement(ApiProvider, { apis: apiHolder }, /* @__PURE__ */ React.createElement(AppContextProvider, { appContext }, /* @__PURE__ */ React.createElement(AppThemeProvider, null, /* @__PURE__ */ React.createElement(RoutingProvider, { ...routeInfo, routeBindings: /* @__PURE__ */ new Map(
|
|
1555
|
+
/* TODO */
|
|
1556
|
+
) }, /* @__PURE__ */ React.createElement(BrowserRouter, null, rootElements)))));
|
|
1236
1557
|
return { default: App };
|
|
1237
1558
|
}
|
|
1238
1559
|
return {
|
|
@@ -1242,25 +1563,35 @@ function createApp(options) {
|
|
|
1242
1563
|
}
|
|
1243
1564
|
};
|
|
1244
1565
|
}
|
|
1566
|
+
const legacyPluginStore = getOrCreateGlobalSingleton(
|
|
1567
|
+
"legacy-plugin-compatibility-store",
|
|
1568
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
1569
|
+
);
|
|
1245
1570
|
function toLegacyPlugin(plugin) {
|
|
1571
|
+
let legacy = legacyPluginStore.get(plugin);
|
|
1572
|
+
if (legacy) {
|
|
1573
|
+
return legacy;
|
|
1574
|
+
}
|
|
1246
1575
|
const errorMsg = "Not implemented in legacy plugin compatibility layer";
|
|
1247
1576
|
const notImplemented = () => {
|
|
1248
1577
|
throw new Error(errorMsg);
|
|
1249
1578
|
};
|
|
1250
|
-
|
|
1579
|
+
legacy = {
|
|
1251
1580
|
getId() {
|
|
1252
1581
|
return plugin.id;
|
|
1253
1582
|
},
|
|
1254
1583
|
get routes() {
|
|
1255
|
-
|
|
1584
|
+
return {};
|
|
1256
1585
|
},
|
|
1257
1586
|
get externalRoutes() {
|
|
1258
|
-
|
|
1587
|
+
return {};
|
|
1259
1588
|
},
|
|
1260
1589
|
getApis: notImplemented,
|
|
1261
1590
|
getFeatureFlags: notImplemented,
|
|
1262
1591
|
provide: notImplemented
|
|
1263
1592
|
};
|
|
1593
|
+
legacyPluginStore.set(plugin, legacy);
|
|
1594
|
+
return legacy;
|
|
1264
1595
|
}
|
|
1265
1596
|
function createLegacyAppContext(plugins) {
|
|
1266
1597
|
return {
|
|
@@ -1343,33 +1674,6 @@ function createApiHolder(coreExtension, configApi) {
|
|
|
1343
1674
|
ApiResolver.validateFactories(factoryRegistry, factoryRegistry.getAllApis());
|
|
1344
1675
|
return new ApiResolver(factoryRegistry);
|
|
1345
1676
|
}
|
|
1346
|
-
function extractRouteInfoFromInstanceTree(roots) {
|
|
1347
|
-
const results = /* @__PURE__ */ new Map();
|
|
1348
|
-
function visit(current, basePath) {
|
|
1349
|
-
var _a;
|
|
1350
|
-
const routePath = (_a = current.getData(coreExtensionData.routePath)) != null ? _a : "";
|
|
1351
|
-
const routeRef = current.getData(coreExtensionData.routeRef);
|
|
1352
|
-
const fullPath = basePath + routePath;
|
|
1353
|
-
if (routeRef) {
|
|
1354
|
-
const routeRefId = routeRef.id;
|
|
1355
|
-
if (routeRefId !== current.id) {
|
|
1356
|
-
throw new Error(
|
|
1357
|
-
`Route ref '${routeRefId}' must have the same ID as extension '${current.id}'`
|
|
1358
|
-
);
|
|
1359
|
-
}
|
|
1360
|
-
results.set(routeRef, fullPath);
|
|
1361
|
-
}
|
|
1362
|
-
for (const children of current.attachments.values()) {
|
|
1363
|
-
for (const child of children) {
|
|
1364
|
-
visit(child, fullPath);
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
for (const root of roots) {
|
|
1369
|
-
visit(root, "");
|
|
1370
|
-
}
|
|
1371
|
-
return results;
|
|
1372
|
-
}
|
|
1373
1677
|
|
|
1374
1678
|
export { createApp, createExtensionTree };
|
|
1375
1679
|
//# sourceMappingURL=index.esm.js.map
|