@backstage/core-app-api 1.2.1-next.2 → 1.3.0-next.4
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 +72 -0
- package/dist/index.d.ts +52 -1
- package/dist/index.esm.js +218 -133
- package/dist/index.esm.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# @backstage/core-app-api
|
|
2
2
|
|
|
3
|
+
## 1.3.0-next.4
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e0d9c9559a: Added a new `AppRouter` component and `app.createRoot()` method that replaces `app.getRouter()` and `app.getProvider()`, which are now deprecated. The new `AppRouter` component is a drop-in replacement for the old router component, while the new `app.createRoot()` method is used instead of the old provider component.
|
|
8
|
+
|
|
9
|
+
An old app setup might look like this:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
const app = createApp(/* ... */);
|
|
13
|
+
|
|
14
|
+
const AppProvider = app.getProvider();
|
|
15
|
+
const AppRouter = app.getRouter();
|
|
16
|
+
|
|
17
|
+
const routes = ...;
|
|
18
|
+
|
|
19
|
+
const App = () => (
|
|
20
|
+
<AppProvider>
|
|
21
|
+
<AlertDisplay />
|
|
22
|
+
<OAuthRequestDialog />
|
|
23
|
+
<AppRouter>
|
|
24
|
+
<Root>{routes}</Root>
|
|
25
|
+
</AppRouter>
|
|
26
|
+
</AppProvider>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export default App;
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
With these new APIs, the setup now looks like this:
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { AppRouter } from '@backstage/core-app-api';
|
|
36
|
+
|
|
37
|
+
const app = createApp(/* ... */);
|
|
38
|
+
|
|
39
|
+
const routes = ...;
|
|
40
|
+
|
|
41
|
+
export default app.createRoot(
|
|
42
|
+
<>
|
|
43
|
+
<AlertDisplay />
|
|
44
|
+
<OAuthRequestDialog />
|
|
45
|
+
<AppRouter>
|
|
46
|
+
<Root>{routes}</Root>
|
|
47
|
+
</AppRouter>
|
|
48
|
+
</>,
|
|
49
|
+
);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Note that `app.createRoot()` accepts a React element, rather than a component.
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- b05dcd5530: Move the `zod` dependency to a version that does not collide with other libraries
|
|
57
|
+
- Updated dependencies
|
|
58
|
+
- @backstage/config@1.0.5-next.1
|
|
59
|
+
- @backstage/core-plugin-api@1.2.0-next.2
|
|
60
|
+
- @backstage/types@1.0.2-next.1
|
|
61
|
+
- @backstage/version-bridge@1.0.3-next.0
|
|
62
|
+
|
|
63
|
+
## 1.2.1-next.3
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- 6870b43dd1: Fix for the automatic rewriting of base URLs.
|
|
68
|
+
- 653d7912ac: Made `WebStorage` notify its subscribers when `localStorage` values change in other tabs/windows
|
|
69
|
+
- Updated dependencies
|
|
70
|
+
- @backstage/config@1.0.5-next.1
|
|
71
|
+
- @backstage/core-plugin-api@1.2.0-next.2
|
|
72
|
+
- @backstage/types@1.0.2-next.1
|
|
73
|
+
- @backstage/version-bridge@1.0.3-next.0
|
|
74
|
+
|
|
3
75
|
## 1.2.1-next.2
|
|
4
76
|
|
|
5
77
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -535,22 +535,45 @@ declare class WebStorage implements StorageApi {
|
|
|
535
535
|
private readonly namespace;
|
|
536
536
|
private readonly errorApi;
|
|
537
537
|
constructor(namespace: string, errorApi: ErrorApi);
|
|
538
|
+
private static hasSubscribed;
|
|
538
539
|
static create(options: {
|
|
539
540
|
errorApi: ErrorApi;
|
|
540
541
|
namespace?: string;
|
|
541
542
|
}): WebStorage;
|
|
543
|
+
private static addStorageEventListener;
|
|
542
544
|
get<T>(key: string): T | undefined;
|
|
543
545
|
snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T>;
|
|
544
546
|
forBucket(name: string): WebStorage;
|
|
545
547
|
set<T>(key: string, data: T): Promise<void>;
|
|
546
548
|
remove(key: string): Promise<void>;
|
|
547
549
|
observe$<T extends JsonValue>(key: string): Observable<StorageValueSnapshot<T>>;
|
|
550
|
+
private handleStorageChange;
|
|
548
551
|
private getKeyName;
|
|
549
552
|
private notifyChanges;
|
|
550
553
|
private subscribers;
|
|
551
554
|
private readonly observable;
|
|
552
555
|
}
|
|
553
556
|
|
|
557
|
+
/**
|
|
558
|
+
* Props for the {@link AppRouter} component.
|
|
559
|
+
* @public
|
|
560
|
+
*/
|
|
561
|
+
interface AppRouterProps {
|
|
562
|
+
children?: ReactNode;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* App router and sign-in page wrapper.
|
|
566
|
+
*
|
|
567
|
+
* @public
|
|
568
|
+
* @remarks
|
|
569
|
+
*
|
|
570
|
+
* The AppRouter provides the routing context and renders the sign-in page.
|
|
571
|
+
* Until the user has successfully signed in, this component will render
|
|
572
|
+
* the sign-in page. Once the user has signed-in, it will instead render
|
|
573
|
+
* the app, while providing routing and route tracking for the app.
|
|
574
|
+
*/
|
|
575
|
+
declare function AppRouter(props: AppRouterProps): JSX.Element;
|
|
576
|
+
|
|
554
577
|
/**
|
|
555
578
|
* Props for the `BootErrorPage` component of {@link AppComponents}.
|
|
556
579
|
*
|
|
@@ -797,14 +820,42 @@ declare type BackstageApp = {
|
|
|
797
820
|
* Get a common or custom icon for this app.
|
|
798
821
|
*/
|
|
799
822
|
getSystemIcon(key: string): IconComponent | undefined;
|
|
823
|
+
/**
|
|
824
|
+
* Creates the root component that renders the entire app.
|
|
825
|
+
*
|
|
826
|
+
* @remarks
|
|
827
|
+
*
|
|
828
|
+
* This method must only be called once, and you have to provide it the entire
|
|
829
|
+
* app element tree. The element tree will be analyzed to discover plugins,
|
|
830
|
+
* routes, and other app features. The returned component will render all
|
|
831
|
+
* of the app elements wrapped within the app context provider.
|
|
832
|
+
*
|
|
833
|
+
* @example
|
|
834
|
+
* ```tsx
|
|
835
|
+
* export default app.createRoot(
|
|
836
|
+
* <>
|
|
837
|
+
* <AlertDisplay />
|
|
838
|
+
* <OAuthRequestDialog />
|
|
839
|
+
* <AppRouter>
|
|
840
|
+
* <Root>{routes}</Root>
|
|
841
|
+
* </AppRouter>
|
|
842
|
+
* </>,
|
|
843
|
+
* );
|
|
844
|
+
* ```
|
|
845
|
+
*/
|
|
846
|
+
createRoot(element: JSX.Element): ComponentType<{}>;
|
|
800
847
|
/**
|
|
801
848
|
* Provider component that should wrap the Router created with getRouter()
|
|
802
849
|
* and any other components that need to be within the app context.
|
|
850
|
+
*
|
|
851
|
+
* @deprecated Use {@link BackstageApp.createRoot} instead.
|
|
803
852
|
*/
|
|
804
853
|
getProvider(): ComponentType<{}>;
|
|
805
854
|
/**
|
|
806
855
|
* Router component that should wrap the App Routes create with getRoutes()
|
|
807
856
|
* and any other components that should only be available while signed in.
|
|
857
|
+
*
|
|
858
|
+
* @deprecated Import and use the {@link AppRouter} component from `@backstage/core-app-api` instead
|
|
808
859
|
*/
|
|
809
860
|
getRouter(): ComponentType<{}>;
|
|
810
861
|
};
|
|
@@ -904,4 +955,4 @@ declare type FeatureFlaggedProps = {
|
|
|
904
955
|
*/
|
|
905
956
|
declare const FeatureFlagged: (props: FeatureFlaggedProps) => JSX.Element;
|
|
906
957
|
|
|
907
|
-
export { AlertApiForwarder, ApiFactoryHolder, ApiFactoryRegistry, ApiFactoryScope, ApiProvider, ApiProviderProps, ApiResolver, AppComponents, AppConfigLoader, AppContext, AppIcons, AppOptions, AppRouteBinder, AppThemeSelector, AtlassianAuth, AuthApiCreateOptions, BackstageApp, BitbucketAuth, BitbucketSession, BootErrorPageProps, ErrorAlerter, ErrorApiForwarder, ErrorBoundaryFallbackProps, FeatureFlagged, FeatureFlaggedProps, FetchMiddleware, FetchMiddlewares, FlatRoutes, FlatRoutesProps, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuth2CreateOptions, OAuth2Session, OAuthApiCreateOptions, OAuthRequestManager, OktaAuth, OneLoginAuth, OneLoginAuthCreateOptions, SamlAuth, SignInPageProps, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
|
|
958
|
+
export { AlertApiForwarder, ApiFactoryHolder, ApiFactoryRegistry, ApiFactoryScope, ApiProvider, ApiProviderProps, ApiResolver, AppComponents, AppConfigLoader, AppContext, AppIcons, AppOptions, AppRouteBinder, AppRouter, AppRouterProps, AppThemeSelector, AtlassianAuth, AuthApiCreateOptions, BackstageApp, BitbucketAuth, BitbucketSession, BootErrorPageProps, ErrorAlerter, ErrorApiForwarder, ErrorBoundaryFallbackProps, FeatureFlagged, FeatureFlaggedProps, FetchMiddleware, FetchMiddlewares, FlatRoutes, FlatRoutesProps, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuth2CreateOptions, OAuth2Session, OAuthApiCreateOptions, OAuthRequestManager, OktaAuth, OneLoginAuth, OneLoginAuthCreateOptions, SamlAuth, SignInPageProps, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React, { useContext,
|
|
1
|
+
import React, { useContext, createContext, useEffect, useState, Children, isValidElement, useMemo, useRef } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { createVersionedContext, createVersionedValueMap, getOrCreateGlobalSingleton } from '@backstage/version-bridge';
|
|
4
4
|
import ObservableImpl from 'zen-observable';
|
|
5
|
-
import { SessionState, FeatureFlagState,
|
|
5
|
+
import { SessionState, FeatureFlagState, AnalyticsContext, useAnalytics, useApp, useApi, configApiRef, getComponentData, attachComponentData, featureFlagsApiRef, appThemeApiRef, identityApiRef, useElementFilter } from '@backstage/core-plugin-api';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { ConfigReader } from '@backstage/config';
|
|
8
8
|
export { ConfigReader } from '@backstage/config';
|
|
9
|
-
import {
|
|
9
|
+
import { createRoutesFromChildren, Route, useLocation, matchRoutes, Routes, generatePath, useRoutes } from 'react-router-dom';
|
|
10
10
|
import useAsync from 'react-use/lib/useAsync';
|
|
11
11
|
import useObservable from 'react-use/lib/useObservable';
|
|
12
12
|
|
|
@@ -1613,7 +1613,7 @@ class OAuthRequestManager {
|
|
|
1613
1613
|
}
|
|
1614
1614
|
|
|
1615
1615
|
const buckets = /* @__PURE__ */ new Map();
|
|
1616
|
-
class
|
|
1616
|
+
const _WebStorage = class {
|
|
1617
1617
|
constructor(namespace, errorApi) {
|
|
1618
1618
|
this.namespace = namespace;
|
|
1619
1619
|
this.errorApi = errorApi;
|
|
@@ -1627,7 +1627,17 @@ class WebStorage {
|
|
|
1627
1627
|
}
|
|
1628
1628
|
static create(options) {
|
|
1629
1629
|
var _a;
|
|
1630
|
-
return new
|
|
1630
|
+
return new _WebStorage((_a = options.namespace) != null ? _a : "", options.errorApi);
|
|
1631
|
+
}
|
|
1632
|
+
static addStorageEventListener() {
|
|
1633
|
+
window.addEventListener("storage", (event) => {
|
|
1634
|
+
var _a;
|
|
1635
|
+
for (const [bucketPath, webStorage] of buckets.entries()) {
|
|
1636
|
+
if ((_a = event.key) == null ? void 0 : _a.startsWith(bucketPath)) {
|
|
1637
|
+
webStorage.handleStorageChange(event.key);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1631
1641
|
}
|
|
1632
1642
|
get(key) {
|
|
1633
1643
|
return this.snapshot(key).value;
|
|
@@ -1656,7 +1666,7 @@ class WebStorage {
|
|
|
1656
1666
|
forBucket(name) {
|
|
1657
1667
|
const bucketPath = `${this.namespace}/${name}`;
|
|
1658
1668
|
if (!buckets.has(bucketPath)) {
|
|
1659
|
-
buckets.set(bucketPath, new
|
|
1669
|
+
buckets.set(bucketPath, new _WebStorage(bucketPath, this.errorApi));
|
|
1660
1670
|
}
|
|
1661
1671
|
return buckets.get(bucketPath);
|
|
1662
1672
|
}
|
|
@@ -1669,8 +1679,21 @@ class WebStorage {
|
|
|
1669
1679
|
this.notifyChanges(key);
|
|
1670
1680
|
}
|
|
1671
1681
|
observe$(key) {
|
|
1682
|
+
if (!_WebStorage.hasSubscribed) {
|
|
1683
|
+
_WebStorage.addStorageEventListener();
|
|
1684
|
+
_WebStorage.hasSubscribed = true;
|
|
1685
|
+
}
|
|
1672
1686
|
return this.observable.filter(({ key: messageKey }) => messageKey === key);
|
|
1673
1687
|
}
|
|
1688
|
+
handleStorageChange(eventKey) {
|
|
1689
|
+
if (!(eventKey == null ? void 0 : eventKey.startsWith(this.namespace))) {
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
const trimmedKey = eventKey == null ? void 0 : eventKey.slice(`${this.namespace}/`.length);
|
|
1693
|
+
if (!trimmedKey.includes("/")) {
|
|
1694
|
+
this.notifyChanges(decodeURIComponent(trimmedKey));
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1674
1697
|
getKeyName(key) {
|
|
1675
1698
|
return `${this.namespace}/${encodeURIComponent(key)}`;
|
|
1676
1699
|
}
|
|
@@ -1680,6 +1703,147 @@ class WebStorage {
|
|
|
1680
1703
|
subscription.next(snapshot);
|
|
1681
1704
|
}
|
|
1682
1705
|
}
|
|
1706
|
+
};
|
|
1707
|
+
let WebStorage = _WebStorage;
|
|
1708
|
+
WebStorage.hasSubscribed = false;
|
|
1709
|
+
|
|
1710
|
+
const InternalAppContext = createContext(void 0);
|
|
1711
|
+
|
|
1712
|
+
function isReactRouterBeta() {
|
|
1713
|
+
const [obj] = createRoutesFromChildren(/* @__PURE__ */ React.createElement(Route, { index: true, element: /* @__PURE__ */ React.createElement("div", null) }));
|
|
1714
|
+
return !obj.index;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
const getExtensionContext = (pathname, routes) => {
|
|
1718
|
+
var _a, _b;
|
|
1719
|
+
try {
|
|
1720
|
+
const matches = matchRoutes(routes, { pathname });
|
|
1721
|
+
const routeObject = (_a = matches == null ? void 0 : matches.filter((match) => {
|
|
1722
|
+
var _a2;
|
|
1723
|
+
return ((_a2 = match == null ? void 0 : match.route.routeRefs) == null ? void 0 : _a2.size) > 0;
|
|
1724
|
+
}).pop()) == null ? void 0 : _a.route;
|
|
1725
|
+
if (!routeObject) {
|
|
1726
|
+
return {};
|
|
1727
|
+
}
|
|
1728
|
+
let routeRef;
|
|
1729
|
+
if (routeObject.routeRefs.size === 1) {
|
|
1730
|
+
routeRef = routeObject.routeRefs.values().next().value;
|
|
1731
|
+
}
|
|
1732
|
+
return {
|
|
1733
|
+
extension: "App",
|
|
1734
|
+
pluginId: ((_b = routeObject.plugin) == null ? void 0 : _b.getId()) || "root",
|
|
1735
|
+
...routeRef ? { routeRef: routeRef.id } : {}
|
|
1736
|
+
};
|
|
1737
|
+
} catch {
|
|
1738
|
+
return {};
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1741
|
+
const TrackNavigation = ({
|
|
1742
|
+
pathname,
|
|
1743
|
+
search,
|
|
1744
|
+
hash
|
|
1745
|
+
}) => {
|
|
1746
|
+
const analytics = useAnalytics();
|
|
1747
|
+
useEffect(() => {
|
|
1748
|
+
analytics.captureEvent("navigate", `${pathname}${search}${hash}`);
|
|
1749
|
+
}, [analytics, pathname, search, hash]);
|
|
1750
|
+
return null;
|
|
1751
|
+
};
|
|
1752
|
+
const RouteTracker = ({
|
|
1753
|
+
routeObjects
|
|
1754
|
+
}) => {
|
|
1755
|
+
const { pathname, search, hash } = useLocation();
|
|
1756
|
+
return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: getExtensionContext(pathname, routeObjects) }, /* @__PURE__ */ React.createElement(TrackNavigation, { pathname, search, hash }));
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
function getBasePath(configApi) {
|
|
1760
|
+
if (!isReactRouterBeta()) {
|
|
1761
|
+
return "";
|
|
1762
|
+
}
|
|
1763
|
+
return readBasePath(configApi);
|
|
1764
|
+
}
|
|
1765
|
+
function readBasePath(configApi) {
|
|
1766
|
+
var _a;
|
|
1767
|
+
let { pathname } = new URL(
|
|
1768
|
+
(_a = configApi.getOptionalString("app.baseUrl")) != null ? _a : "/",
|
|
1769
|
+
"http://sample.dev"
|
|
1770
|
+
);
|
|
1771
|
+
pathname = pathname.replace(/\/*$/, "");
|
|
1772
|
+
return pathname;
|
|
1773
|
+
}
|
|
1774
|
+
function SignInPageWrapper({
|
|
1775
|
+
component: Component,
|
|
1776
|
+
appIdentityProxy,
|
|
1777
|
+
children
|
|
1778
|
+
}) {
|
|
1779
|
+
const [identityApi, setIdentityApi] = useState();
|
|
1780
|
+
const configApi = useApi(configApiRef);
|
|
1781
|
+
const basePath = getBasePath(configApi);
|
|
1782
|
+
if (!identityApi) {
|
|
1783
|
+
return /* @__PURE__ */ React.createElement(Component, { onSignInSuccess: setIdentityApi });
|
|
1784
|
+
}
|
|
1785
|
+
appIdentityProxy.setTarget(identityApi, {
|
|
1786
|
+
signOutTargetUrl: basePath || "/"
|
|
1787
|
+
});
|
|
1788
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
|
|
1789
|
+
}
|
|
1790
|
+
function AppRouter(props) {
|
|
1791
|
+
const { Router: RouterComponent, SignInPage: SignInPageComponent } = useApp().getComponents();
|
|
1792
|
+
const configApi = useApi(configApiRef);
|
|
1793
|
+
const basePath = readBasePath(configApi);
|
|
1794
|
+
const mountPath = `${basePath}/*`;
|
|
1795
|
+
const internalAppContext = useContext(InternalAppContext);
|
|
1796
|
+
if (!internalAppContext) {
|
|
1797
|
+
throw new Error("AppRouter must be rendered within the AppProvider");
|
|
1798
|
+
}
|
|
1799
|
+
const { routeObjects, appIdentityProxy } = internalAppContext;
|
|
1800
|
+
if (!SignInPageComponent) {
|
|
1801
|
+
appIdentityProxy.setTarget(
|
|
1802
|
+
{
|
|
1803
|
+
getUserId: () => "guest",
|
|
1804
|
+
getIdToken: async () => void 0,
|
|
1805
|
+
getProfile: () => ({
|
|
1806
|
+
email: "guest@example.com",
|
|
1807
|
+
displayName: "Guest"
|
|
1808
|
+
}),
|
|
1809
|
+
getProfileInfo: async () => ({
|
|
1810
|
+
email: "guest@example.com",
|
|
1811
|
+
displayName: "Guest"
|
|
1812
|
+
}),
|
|
1813
|
+
getBackstageIdentity: async () => ({
|
|
1814
|
+
type: "user",
|
|
1815
|
+
userEntityRef: "user:default/guest",
|
|
1816
|
+
ownershipEntityRefs: ["user:default/guest"]
|
|
1817
|
+
}),
|
|
1818
|
+
getCredentials: async () => ({}),
|
|
1819
|
+
signOut: async () => {
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
{ signOutTargetUrl: basePath || "/" }
|
|
1823
|
+
);
|
|
1824
|
+
if (isReactRouterBeta()) {
|
|
1825
|
+
return /* @__PURE__ */ React.createElement(RouterComponent, null, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: mountPath, element: /* @__PURE__ */ React.createElement(React.Fragment, null, props.children) })));
|
|
1826
|
+
}
|
|
1827
|
+
return /* @__PURE__ */ React.createElement(RouterComponent, { basename: basePath }, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), props.children);
|
|
1828
|
+
}
|
|
1829
|
+
if (isReactRouterBeta()) {
|
|
1830
|
+
return /* @__PURE__ */ React.createElement(RouterComponent, null, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), /* @__PURE__ */ React.createElement(
|
|
1831
|
+
SignInPageWrapper,
|
|
1832
|
+
{
|
|
1833
|
+
component: SignInPageComponent,
|
|
1834
|
+
appIdentityProxy
|
|
1835
|
+
},
|
|
1836
|
+
/* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: mountPath, element: /* @__PURE__ */ React.createElement(React.Fragment, null, props.children) }))
|
|
1837
|
+
));
|
|
1838
|
+
}
|
|
1839
|
+
return /* @__PURE__ */ React.createElement(RouterComponent, { basename: basePath }, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), /* @__PURE__ */ React.createElement(
|
|
1840
|
+
SignInPageWrapper,
|
|
1841
|
+
{
|
|
1842
|
+
component: SignInPageComponent,
|
|
1843
|
+
appIdentityProxy
|
|
1844
|
+
},
|
|
1845
|
+
props.children
|
|
1846
|
+
));
|
|
1683
1847
|
}
|
|
1684
1848
|
|
|
1685
1849
|
function traverseElementTree(options) {
|
|
@@ -2173,48 +2337,6 @@ const RoutingProvider = ({
|
|
|
2173
2337
|
return /* @__PURE__ */ React.createElement(RoutingContext.Provider, { value: versionedValue }, children);
|
|
2174
2338
|
};
|
|
2175
2339
|
|
|
2176
|
-
const getExtensionContext = (pathname, routes) => {
|
|
2177
|
-
var _a, _b;
|
|
2178
|
-
try {
|
|
2179
|
-
const matches = matchRoutes(routes, { pathname });
|
|
2180
|
-
const routeObject = (_a = matches == null ? void 0 : matches.filter((match) => {
|
|
2181
|
-
var _a2;
|
|
2182
|
-
return ((_a2 = match == null ? void 0 : match.route.routeRefs) == null ? void 0 : _a2.size) > 0;
|
|
2183
|
-
}).pop()) == null ? void 0 : _a.route;
|
|
2184
|
-
if (!routeObject) {
|
|
2185
|
-
return {};
|
|
2186
|
-
}
|
|
2187
|
-
let routeRef;
|
|
2188
|
-
if (routeObject.routeRefs.size === 1) {
|
|
2189
|
-
routeRef = routeObject.routeRefs.values().next().value;
|
|
2190
|
-
}
|
|
2191
|
-
return {
|
|
2192
|
-
extension: "App",
|
|
2193
|
-
pluginId: ((_b = routeObject.plugin) == null ? void 0 : _b.getId()) || "root",
|
|
2194
|
-
...routeRef ? { routeRef: routeRef.id } : {}
|
|
2195
|
-
};
|
|
2196
|
-
} catch {
|
|
2197
|
-
return {};
|
|
2198
|
-
}
|
|
2199
|
-
};
|
|
2200
|
-
const TrackNavigation = ({
|
|
2201
|
-
pathname,
|
|
2202
|
-
search,
|
|
2203
|
-
hash
|
|
2204
|
-
}) => {
|
|
2205
|
-
const analytics = useAnalytics();
|
|
2206
|
-
useEffect(() => {
|
|
2207
|
-
analytics.captureEvent("navigate", `${pathname}${search}${hash}`);
|
|
2208
|
-
}, [analytics, pathname, search, hash]);
|
|
2209
|
-
return null;
|
|
2210
|
-
};
|
|
2211
|
-
const RouteTracker = ({
|
|
2212
|
-
routeObjects
|
|
2213
|
-
}) => {
|
|
2214
|
-
const { pathname, search, hash } = useLocation();
|
|
2215
|
-
return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: getExtensionContext(pathname, routeObjects) }, /* @__PURE__ */ React.createElement(TrackNavigation, { pathname, search, hash }));
|
|
2216
|
-
};
|
|
2217
|
-
|
|
2218
2340
|
function validateRouteParameters(routePaths, routeParents) {
|
|
2219
2341
|
const notLeafRoutes = new Set(routeParents.values());
|
|
2220
2342
|
notLeafRoutes.delete(void 0);
|
|
@@ -2493,27 +2615,25 @@ function resolveRouteBindings(bindRoutes) {
|
|
|
2493
2615
|
return result;
|
|
2494
2616
|
}
|
|
2495
2617
|
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
}
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
return pathname;
|
|
2516
|
-
}
|
|
2618
|
+
var __accessCheck = (obj, member, msg) => {
|
|
2619
|
+
if (!member.has(obj))
|
|
2620
|
+
throw TypeError("Cannot " + msg);
|
|
2621
|
+
};
|
|
2622
|
+
var __privateGet = (obj, member, getter) => {
|
|
2623
|
+
__accessCheck(obj, member, "read from private field");
|
|
2624
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
2625
|
+
};
|
|
2626
|
+
var __privateAdd = (obj, member, value) => {
|
|
2627
|
+
if (member.has(obj))
|
|
2628
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
2629
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
2630
|
+
};
|
|
2631
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
2632
|
+
__accessCheck(obj, member, "write to private field");
|
|
2633
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
2634
|
+
return value;
|
|
2635
|
+
};
|
|
2636
|
+
var _getProviderCalled;
|
|
2517
2637
|
function useConfigLoader(configLoader, components, appThemeApi) {
|
|
2518
2638
|
var _a;
|
|
2519
2639
|
const hasConfig = Boolean(configLoader);
|
|
@@ -2540,7 +2660,7 @@ function useConfigLoader(configLoader, components, appThemeApi) {
|
|
|
2540
2660
|
return new URL(
|
|
2541
2661
|
fullUrl.replace(getOrigin(fullUrl), ""),
|
|
2542
2662
|
document.location.origin
|
|
2543
|
-
).href;
|
|
2663
|
+
).href.replace(/\/$/, "");
|
|
2544
2664
|
};
|
|
2545
2665
|
const appBaseUrl = urlConfigReader.getOptionalString("app.baseUrl");
|
|
2546
2666
|
const backendBaseUrl = urlConfigReader.getOptionalString("backend.baseUrl");
|
|
@@ -2553,15 +2673,17 @@ function useConfigLoader(configLoader, components, appThemeApi) {
|
|
|
2553
2673
|
const appOrigin = getOrigin(appBaseUrl);
|
|
2554
2674
|
const backendOrigin = getOrigin(backendBaseUrl);
|
|
2555
2675
|
if (appOrigin === backendOrigin) {
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2676
|
+
const newBackendBaseUrl = overrideOrigin(backendBaseUrl);
|
|
2677
|
+
if (backendBaseUrl !== newBackendBaseUrl) {
|
|
2678
|
+
relativeResolverConfig.data.backend = { baseUrl: newBackendBaseUrl };
|
|
2679
|
+
}
|
|
2559
2680
|
}
|
|
2560
2681
|
}
|
|
2561
2682
|
if (appBaseUrl) {
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2683
|
+
const newAppBaseUrl = overrideOrigin(appBaseUrl);
|
|
2684
|
+
if (appBaseUrl !== newAppBaseUrl) {
|
|
2685
|
+
relativeResolverConfig.data.app = { baseUrl: newAppBaseUrl };
|
|
2686
|
+
}
|
|
2565
2687
|
}
|
|
2566
2688
|
if (Object.keys(relativeResolverConfig.data).length) {
|
|
2567
2689
|
configs = configs.concat([relativeResolverConfig]);
|
|
@@ -2592,6 +2714,7 @@ class AppContextImpl {
|
|
|
2592
2714
|
class AppManager {
|
|
2593
2715
|
constructor(options) {
|
|
2594
2716
|
this.appIdentityProxy = new AppIdentityProxy();
|
|
2717
|
+
__privateAdd(this, _getProviderCalled, false);
|
|
2595
2718
|
var _a, _b, _c, _d;
|
|
2596
2719
|
this.apis = (_a = options.apis) != null ? _a : [];
|
|
2597
2720
|
this.icons = options.icons;
|
|
@@ -2615,7 +2738,20 @@ class AppManager {
|
|
|
2615
2738
|
getComponents() {
|
|
2616
2739
|
return this.components;
|
|
2617
2740
|
}
|
|
2741
|
+
createRoot(element) {
|
|
2742
|
+
const AppProvider = this.getProvider();
|
|
2743
|
+
const AppRoot = () => {
|
|
2744
|
+
return /* @__PURE__ */ React.createElement(AppProvider, null, element);
|
|
2745
|
+
};
|
|
2746
|
+
return AppRoot;
|
|
2747
|
+
}
|
|
2618
2748
|
getProvider() {
|
|
2749
|
+
if (__privateGet(this, _getProviderCalled)) {
|
|
2750
|
+
throw new Error(
|
|
2751
|
+
"app.getProvider() or app.createRoot() has already been called, and can only be called once"
|
|
2752
|
+
);
|
|
2753
|
+
}
|
|
2754
|
+
__privateSet(this, _getProviderCalled, true);
|
|
2619
2755
|
const appContext = new AppContextImpl(this);
|
|
2620
2756
|
let routesHaveBeenValidated = false;
|
|
2621
2757
|
const Provider = ({ children }) => {
|
|
@@ -2708,7 +2844,10 @@ class AppManager {
|
|
|
2708
2844
|
/* @__PURE__ */ React.createElement(
|
|
2709
2845
|
InternalAppContext.Provider,
|
|
2710
2846
|
{
|
|
2711
|
-
value: {
|
|
2847
|
+
value: {
|
|
2848
|
+
routeObjects: routing.objects,
|
|
2849
|
+
appIdentityProxy: this.appIdentityProxy
|
|
2850
|
+
}
|
|
2712
2851
|
},
|
|
2713
2852
|
children
|
|
2714
2853
|
)
|
|
@@ -2717,61 +2856,6 @@ class AppManager {
|
|
|
2717
2856
|
return Provider;
|
|
2718
2857
|
}
|
|
2719
2858
|
getRouter() {
|
|
2720
|
-
const { Router: RouterComponent, SignInPage: SignInPageComponent } = this.components;
|
|
2721
|
-
const SignInPageWrapper = ({
|
|
2722
|
-
component: Component,
|
|
2723
|
-
children
|
|
2724
|
-
}) => {
|
|
2725
|
-
const [identityApi, setIdentityApi] = useState();
|
|
2726
|
-
const configApi = useApi(configApiRef);
|
|
2727
|
-
const basePath = getBasePath(configApi);
|
|
2728
|
-
if (!identityApi) {
|
|
2729
|
-
return /* @__PURE__ */ React.createElement(Component, { onSignInSuccess: setIdentityApi });
|
|
2730
|
-
}
|
|
2731
|
-
this.appIdentityProxy.setTarget(identityApi, {
|
|
2732
|
-
signOutTargetUrl: basePath || "/"
|
|
2733
|
-
});
|
|
2734
|
-
return children;
|
|
2735
|
-
};
|
|
2736
|
-
const AppRouter = ({ children }) => {
|
|
2737
|
-
const configApi = useApi(configApiRef);
|
|
2738
|
-
const basePath = readBasePath(configApi);
|
|
2739
|
-
const mountPath = `${basePath}/*`;
|
|
2740
|
-
const { routeObjects } = useContext(InternalAppContext);
|
|
2741
|
-
if (!SignInPageComponent) {
|
|
2742
|
-
this.appIdentityProxy.setTarget(
|
|
2743
|
-
{
|
|
2744
|
-
getUserId: () => "guest",
|
|
2745
|
-
getIdToken: async () => void 0,
|
|
2746
|
-
getProfile: () => ({
|
|
2747
|
-
email: "guest@example.com",
|
|
2748
|
-
displayName: "Guest"
|
|
2749
|
-
}),
|
|
2750
|
-
getProfileInfo: async () => ({
|
|
2751
|
-
email: "guest@example.com",
|
|
2752
|
-
displayName: "Guest"
|
|
2753
|
-
}),
|
|
2754
|
-
getBackstageIdentity: async () => ({
|
|
2755
|
-
type: "user",
|
|
2756
|
-
userEntityRef: "user:default/guest",
|
|
2757
|
-
ownershipEntityRefs: ["user:default/guest"]
|
|
2758
|
-
}),
|
|
2759
|
-
getCredentials: async () => ({}),
|
|
2760
|
-
signOut: async () => {
|
|
2761
|
-
}
|
|
2762
|
-
},
|
|
2763
|
-
{ signOutTargetUrl: basePath || "/" }
|
|
2764
|
-
);
|
|
2765
|
-
if (isReactRouterBeta()) {
|
|
2766
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, null, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: mountPath, element: /* @__PURE__ */ React.createElement(React.Fragment, null, children) })));
|
|
2767
|
-
}
|
|
2768
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, { basename: basePath }, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), children);
|
|
2769
|
-
}
|
|
2770
|
-
if (isReactRouterBeta()) {
|
|
2771
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, null, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), /* @__PURE__ */ React.createElement(SignInPageWrapper, { component: SignInPageComponent }, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: mountPath, element: /* @__PURE__ */ React.createElement(React.Fragment, null, children) }))));
|
|
2772
|
-
}
|
|
2773
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, { basename: basePath }, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), /* @__PURE__ */ React.createElement(SignInPageWrapper, { component: SignInPageComponent }, /* @__PURE__ */ React.createElement(React.Fragment, null, children)));
|
|
2774
|
-
};
|
|
2775
2859
|
return AppRouter;
|
|
2776
2860
|
}
|
|
2777
2861
|
getApiHolder() {
|
|
@@ -2853,6 +2937,7 @@ class AppManager {
|
|
|
2853
2937
|
}
|
|
2854
2938
|
}
|
|
2855
2939
|
}
|
|
2940
|
+
_getProviderCalled = new WeakMap();
|
|
2856
2941
|
|
|
2857
2942
|
function createSpecializedApp(options) {
|
|
2858
2943
|
return new AppManager(options);
|
|
@@ -2906,5 +2991,5 @@ const FlatRoutes = (props) => {
|
|
|
2906
2991
|
return useRoutes(withNotFound);
|
|
2907
2992
|
};
|
|
2908
2993
|
|
|
2909
|
-
export { AlertApiForwarder, ApiFactoryRegistry, ApiProvider, ApiResolver, AppThemeSelector, AtlassianAuth, BitbucketAuth, ErrorAlerter, ErrorApiForwarder, FeatureFlagged, FetchMiddlewares, FlatRoutes, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuthRequestManager, OktaAuth, OneLoginAuth, SamlAuth, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
|
|
2994
|
+
export { AlertApiForwarder, ApiFactoryRegistry, ApiProvider, ApiResolver, AppRouter, AppThemeSelector, AtlassianAuth, BitbucketAuth, ErrorAlerter, ErrorApiForwarder, FeatureFlagged, FetchMiddlewares, FlatRoutes, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuthRequestManager, OktaAuth, OneLoginAuth, SamlAuth, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
|
|
2910
2995
|
//# sourceMappingURL=index.esm.js.map
|