@backstage/core-app-api 1.2.1-next.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,135 @@
1
1
  # @backstage/core-app-api
2
2
 
3
+ ## 1.3.0
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
+ - d3fea4ae0a: Internal fixes to avoid implicit usage of globals
57
+ - b05dcd5530: Move the `zod` dependency to a version that does not collide with other libraries
58
+ - b4b5b02315: Tweak feature flag registration so that it happens immediately before the first rendering of the app, rather than just after.
59
+ - 6870b43dd1: Fix for the automatic rewriting of base URLs.
60
+ - 203271b746: Prevent duplicate feature flag components from rendering in the settings when using <FeatureFlagged /> components
61
+ - 3280711113: Updated dependency `msw` to `^0.49.0`.
62
+ - 19356df560: Updated dependency `zen-observable` to `^0.9.0`.
63
+ - c3fa90e184: Updated dependency `zen-observable` to `^0.10.0`.
64
+ - 8015ff1258: Tweaked wording to use inclusive terminology
65
+ - 653d7912ac: Made `WebStorage` notify its subscribers when `localStorage` values change in other tabs/windows
66
+ - 63310e3987: Apps will now rewrite the `app.baseUrl` configuration to match the current `location.origin`. The `backend.baseUrl` will also be rewritten in the same way when the `app.baseUrl` and `backend.baseUrl` have matching origins. This will reduce the need for separate frontend builds for different environments.
67
+ - Updated dependencies
68
+ - @backstage/core-plugin-api@1.2.0
69
+ - @backstage/version-bridge@1.0.3
70
+ - @backstage/types@1.0.2
71
+ - @backstage/config@1.0.5
72
+
73
+ ## 1.3.0-next.4
74
+
75
+ ### Minor Changes
76
+
77
+ - 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.
78
+
79
+ An old app setup might look like this:
80
+
81
+ ```tsx
82
+ const app = createApp(/* ... */);
83
+
84
+ const AppProvider = app.getProvider();
85
+ const AppRouter = app.getRouter();
86
+
87
+ const routes = ...;
88
+
89
+ const App = () => (
90
+ <AppProvider>
91
+ <AlertDisplay />
92
+ <OAuthRequestDialog />
93
+ <AppRouter>
94
+ <Root>{routes}</Root>
95
+ </AppRouter>
96
+ </AppProvider>
97
+ );
98
+
99
+ export default App;
100
+ ```
101
+
102
+ With these new APIs, the setup now looks like this:
103
+
104
+ ```tsx
105
+ import { AppRouter } from '@backstage/core-app-api';
106
+
107
+ const app = createApp(/* ... */);
108
+
109
+ const routes = ...;
110
+
111
+ export default app.createRoot(
112
+ <>
113
+ <AlertDisplay />
114
+ <OAuthRequestDialog />
115
+ <AppRouter>
116
+ <Root>{routes}</Root>
117
+ </AppRouter>
118
+ </>,
119
+ );
120
+ ```
121
+
122
+ Note that `app.createRoot()` accepts a React element, rather than a component.
123
+
124
+ ### Patch Changes
125
+
126
+ - b05dcd5530: Move the `zod` dependency to a version that does not collide with other libraries
127
+ - Updated dependencies
128
+ - @backstage/config@1.0.5-next.1
129
+ - @backstage/core-plugin-api@1.2.0-next.2
130
+ - @backstage/types@1.0.2-next.1
131
+ - @backstage/version-bridge@1.0.3-next.0
132
+
3
133
  ## 1.2.1-next.3
4
134
 
5
135
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -554,6 +554,26 @@ declare class WebStorage implements StorageApi {
554
554
  private readonly observable;
555
555
  }
556
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
+
557
577
  /**
558
578
  * Props for the `BootErrorPage` component of {@link AppComponents}.
559
579
  *
@@ -800,14 +820,42 @@ declare type BackstageApp = {
800
820
  * Get a common or custom icon for this app.
801
821
  */
802
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<{}>;
803
847
  /**
804
848
  * Provider component that should wrap the Router created with getRouter()
805
849
  * and any other components that need to be within the app context.
850
+ *
851
+ * @deprecated Use {@link BackstageApp.createRoot} instead.
806
852
  */
807
853
  getProvider(): ComponentType<{}>;
808
854
  /**
809
855
  * Router component that should wrap the App Routes create with getRoutes()
810
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
811
859
  */
812
860
  getRouter(): ComponentType<{}>;
813
861
  };
@@ -907,4 +955,4 @@ declare type FeatureFlaggedProps = {
907
955
  */
908
956
  declare const FeatureFlagged: (props: FeatureFlaggedProps) => JSX.Element;
909
957
 
910
- 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, Children, isValidElement, useEffect, useMemo, useState, createContext, useRef } from 'react';
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, getComponentData, attachComponentData, useApi, featureFlagsApiRef, AnalyticsContext, useAnalytics, appThemeApiRef, configApiRef, identityApiRef, useApp, useElementFilter } from '@backstage/core-plugin-api';
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 { matchRoutes, generatePath, useLocation, createRoutesFromChildren, Route, Routes, useRoutes } from 'react-router-dom';
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
 
@@ -1707,6 +1707,145 @@ const _WebStorage = class {
1707
1707
  let WebStorage = _WebStorage;
1708
1708
  WebStorage.hasSubscribed = false;
1709
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
+ ));
1847
+ }
1848
+
1710
1849
  function traverseElementTree(options) {
1711
1850
  const collectors = {};
1712
1851
  for (const name in options.collectors) {
@@ -2198,48 +2337,6 @@ const RoutingProvider = ({
2198
2337
  return /* @__PURE__ */ React.createElement(RoutingContext.Provider, { value: versionedValue }, children);
2199
2338
  };
2200
2339
 
2201
- const getExtensionContext = (pathname, routes) => {
2202
- var _a, _b;
2203
- try {
2204
- const matches = matchRoutes(routes, { pathname });
2205
- const routeObject = (_a = matches == null ? void 0 : matches.filter((match) => {
2206
- var _a2;
2207
- return ((_a2 = match == null ? void 0 : match.route.routeRefs) == null ? void 0 : _a2.size) > 0;
2208
- }).pop()) == null ? void 0 : _a.route;
2209
- if (!routeObject) {
2210
- return {};
2211
- }
2212
- let routeRef;
2213
- if (routeObject.routeRefs.size === 1) {
2214
- routeRef = routeObject.routeRefs.values().next().value;
2215
- }
2216
- return {
2217
- extension: "App",
2218
- pluginId: ((_b = routeObject.plugin) == null ? void 0 : _b.getId()) || "root",
2219
- ...routeRef ? { routeRef: routeRef.id } : {}
2220
- };
2221
- } catch {
2222
- return {};
2223
- }
2224
- };
2225
- const TrackNavigation = ({
2226
- pathname,
2227
- search,
2228
- hash
2229
- }) => {
2230
- const analytics = useAnalytics();
2231
- useEffect(() => {
2232
- analytics.captureEvent("navigate", `${pathname}${search}${hash}`);
2233
- }, [analytics, pathname, search, hash]);
2234
- return null;
2235
- };
2236
- const RouteTracker = ({
2237
- routeObjects
2238
- }) => {
2239
- const { pathname, search, hash } = useLocation();
2240
- return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: getExtensionContext(pathname, routeObjects) }, /* @__PURE__ */ React.createElement(TrackNavigation, { pathname, search, hash }));
2241
- };
2242
-
2243
2340
  function validateRouteParameters(routePaths, routeParents) {
2244
2341
  const notLeafRoutes = new Set(routeParents.values());
2245
2342
  notLeafRoutes.delete(void 0);
@@ -2518,27 +2615,25 @@ function resolveRouteBindings(bindRoutes) {
2518
2615
  return result;
2519
2616
  }
2520
2617
 
2521
- function isReactRouterBeta() {
2522
- const [obj] = createRoutesFromChildren(/* @__PURE__ */ React.createElement(Route, { index: true, element: /* @__PURE__ */ React.createElement("div", null) }));
2523
- return !obj.index;
2524
- }
2525
-
2526
- const InternalAppContext = createContext({ routeObjects: [] });
2527
- function getBasePath(configApi) {
2528
- if (!isReactRouterBeta()) {
2529
- return "";
2530
- }
2531
- return readBasePath(configApi);
2532
- }
2533
- function readBasePath(configApi) {
2534
- var _a;
2535
- let { pathname } = new URL(
2536
- (_a = configApi.getOptionalString("app.baseUrl")) != null ? _a : "/",
2537
- "http://sample.dev"
2538
- );
2539
- pathname = pathname.replace(/\/*$/, "");
2540
- return pathname;
2541
- }
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;
2542
2637
  function useConfigLoader(configLoader, components, appThemeApi) {
2543
2638
  var _a;
2544
2639
  const hasConfig = Boolean(configLoader);
@@ -2619,6 +2714,7 @@ class AppContextImpl {
2619
2714
  class AppManager {
2620
2715
  constructor(options) {
2621
2716
  this.appIdentityProxy = new AppIdentityProxy();
2717
+ __privateAdd(this, _getProviderCalled, false);
2622
2718
  var _a, _b, _c, _d;
2623
2719
  this.apis = (_a = options.apis) != null ? _a : [];
2624
2720
  this.icons = options.icons;
@@ -2642,7 +2738,20 @@ class AppManager {
2642
2738
  getComponents() {
2643
2739
  return this.components;
2644
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
+ }
2645
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);
2646
2755
  const appContext = new AppContextImpl(this);
2647
2756
  let routesHaveBeenValidated = false;
2648
2757
  const Provider = ({ children }) => {
@@ -2735,7 +2844,10 @@ class AppManager {
2735
2844
  /* @__PURE__ */ React.createElement(
2736
2845
  InternalAppContext.Provider,
2737
2846
  {
2738
- value: { routeObjects: routing.objects }
2847
+ value: {
2848
+ routeObjects: routing.objects,
2849
+ appIdentityProxy: this.appIdentityProxy
2850
+ }
2739
2851
  },
2740
2852
  children
2741
2853
  )
@@ -2744,61 +2856,6 @@ class AppManager {
2744
2856
  return Provider;
2745
2857
  }
2746
2858
  getRouter() {
2747
- const { Router: RouterComponent, SignInPage: SignInPageComponent } = this.components;
2748
- const SignInPageWrapper = ({
2749
- component: Component,
2750
- children
2751
- }) => {
2752
- const [identityApi, setIdentityApi] = useState();
2753
- const configApi = useApi(configApiRef);
2754
- const basePath = getBasePath(configApi);
2755
- if (!identityApi) {
2756
- return /* @__PURE__ */ React.createElement(Component, { onSignInSuccess: setIdentityApi });
2757
- }
2758
- this.appIdentityProxy.setTarget(identityApi, {
2759
- signOutTargetUrl: basePath || "/"
2760
- });
2761
- return children;
2762
- };
2763
- const AppRouter = ({ children }) => {
2764
- const configApi = useApi(configApiRef);
2765
- const basePath = readBasePath(configApi);
2766
- const mountPath = `${basePath}/*`;
2767
- const { routeObjects } = useContext(InternalAppContext);
2768
- if (!SignInPageComponent) {
2769
- this.appIdentityProxy.setTarget(
2770
- {
2771
- getUserId: () => "guest",
2772
- getIdToken: async () => void 0,
2773
- getProfile: () => ({
2774
- email: "guest@example.com",
2775
- displayName: "Guest"
2776
- }),
2777
- getProfileInfo: async () => ({
2778
- email: "guest@example.com",
2779
- displayName: "Guest"
2780
- }),
2781
- getBackstageIdentity: async () => ({
2782
- type: "user",
2783
- userEntityRef: "user:default/guest",
2784
- ownershipEntityRefs: ["user:default/guest"]
2785
- }),
2786
- getCredentials: async () => ({}),
2787
- signOut: async () => {
2788
- }
2789
- },
2790
- { signOutTargetUrl: basePath || "/" }
2791
- );
2792
- if (isReactRouterBeta()) {
2793
- 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) })));
2794
- }
2795
- return /* @__PURE__ */ React.createElement(RouterComponent, { basename: basePath }, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), children);
2796
- }
2797
- if (isReactRouterBeta()) {
2798
- 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) }))));
2799
- }
2800
- 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)));
2801
- };
2802
2859
  return AppRouter;
2803
2860
  }
2804
2861
  getApiHolder() {
@@ -2880,6 +2937,7 @@ class AppManager {
2880
2937
  }
2881
2938
  }
2882
2939
  }
2940
+ _getProviderCalled = new WeakMap();
2883
2941
 
2884
2942
  function createSpecializedApp(options) {
2885
2943
  return new AppManager(options);
@@ -2933,5 +2991,5 @@ const FlatRoutes = (props) => {
2933
2991
  return useRoutes(withNotFound);
2934
2992
  };
2935
2993
 
2936
- 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 };
2937
2995
  //# sourceMappingURL=index.esm.js.map