@backstage/core-app-api 1.2.1-next.0 → 1.2.1-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 +26 -0
- package/dist/index.esm.js +92 -87
- package/dist/index.esm.js.map +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @backstage/core-app-api
|
|
2
2
|
|
|
3
|
+
## 1.2.1-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b4b5b02315: Tweak feature flag registration so that it happens immediately before the first rendering of the app, rather than just after.
|
|
8
|
+
- 203271b746: Prevent duplicate feature flag components from rendering in the settings when using <FeatureFlagged /> components
|
|
9
|
+
- 8015ff1258: Tweaked wording to use inclusive terminology
|
|
10
|
+
- 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.
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/core-plugin-api@1.2.0-next.2
|
|
13
|
+
- @backstage/config@1.0.5-next.1
|
|
14
|
+
- @backstage/types@1.0.2-next.1
|
|
15
|
+
- @backstage/version-bridge@1.0.3-next.0
|
|
16
|
+
|
|
17
|
+
## 1.2.1-next.1
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- d3fea4ae0a: Internal fixes to avoid implicit usage of globals
|
|
22
|
+
- c3fa90e184: Updated dependency `zen-observable` to `^0.10.0`.
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @backstage/version-bridge@1.0.3-next.0
|
|
25
|
+
- @backstage/core-plugin-api@1.1.1-next.1
|
|
26
|
+
- @backstage/types@1.0.2-next.1
|
|
27
|
+
- @backstage/config@1.0.5-next.1
|
|
28
|
+
|
|
3
29
|
## 1.2.1-next.0
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useContext, Children, isValidElement, useEffect, useMemo, useState, createContext } from 'react';
|
|
1
|
+
import React, { useContext, Children, isValidElement, useEffect, useMemo, useState, createContext, 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';
|
|
@@ -31,10 +31,13 @@ const ApiProvider = (props) => {
|
|
|
31
31
|
const { apis, children } = props;
|
|
32
32
|
const parentHolder = (_a = useContext(ApiContext)) == null ? void 0 : _a.atVersion(1);
|
|
33
33
|
const holder = parentHolder ? new ApiAggregator(apis, parentHolder) : apis;
|
|
34
|
-
return /* @__PURE__ */ React.createElement(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
return /* @__PURE__ */ React.createElement(
|
|
35
|
+
ApiContext.Provider,
|
|
36
|
+
{
|
|
37
|
+
value: createVersionedValueMap({ 1: holder }),
|
|
38
|
+
children
|
|
39
|
+
}
|
|
40
|
+
);
|
|
38
41
|
};
|
|
39
42
|
ApiProvider.propTypes = {
|
|
40
43
|
apis: PropTypes.shape({ get: PropTypes.func.isRequired }).isRequired,
|
|
@@ -279,7 +282,7 @@ class DefaultAuthConnector {
|
|
|
279
282
|
const scope = this.joinScopesFunc(scopes);
|
|
280
283
|
const popupUrl = await this.buildUrl("/start", {
|
|
281
284
|
scope,
|
|
282
|
-
origin: location.origin
|
|
285
|
+
origin: window.location.origin
|
|
283
286
|
});
|
|
284
287
|
const payload = await showLoginPopup({
|
|
285
288
|
url: popupUrl,
|
|
@@ -2167,9 +2170,7 @@ const RoutingProvider = ({
|
|
|
2167
2170
|
basePath
|
|
2168
2171
|
);
|
|
2169
2172
|
const versionedValue = createVersionedValueMap({ 1: resolver });
|
|
2170
|
-
return /* @__PURE__ */ React.createElement(RoutingContext.Provider, {
|
|
2171
|
-
value: versionedValue
|
|
2172
|
-
}, children);
|
|
2173
|
+
return /* @__PURE__ */ React.createElement(RoutingContext.Provider, { value: versionedValue }, children);
|
|
2173
2174
|
};
|
|
2174
2175
|
|
|
2175
2176
|
const getExtensionContext = (pathname, routes) => {
|
|
@@ -2211,13 +2212,7 @@ const RouteTracker = ({
|
|
|
2211
2212
|
routeObjects
|
|
2212
2213
|
}) => {
|
|
2213
2214
|
const { pathname, search, hash } = useLocation();
|
|
2214
|
-
return /* @__PURE__ */ React.createElement(AnalyticsContext, {
|
|
2215
|
-
attributes: getExtensionContext(pathname, routeObjects)
|
|
2216
|
-
}, /* @__PURE__ */ React.createElement(TrackNavigation, {
|
|
2217
|
-
pathname,
|
|
2218
|
-
search,
|
|
2219
|
-
hash
|
|
2220
|
-
}));
|
|
2215
|
+
return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: getExtensionContext(pathname, routeObjects) }, /* @__PURE__ */ React.createElement(TrackNavigation, { pathname, search, hash }));
|
|
2221
2216
|
};
|
|
2222
2217
|
|
|
2223
2218
|
function validateRouteParameters(routePaths, routeParents) {
|
|
@@ -2277,10 +2272,7 @@ const AppContextProvider = ({
|
|
|
2277
2272
|
children
|
|
2278
2273
|
}) => {
|
|
2279
2274
|
const versionedValue = createVersionedValueMap({ 1: appContext });
|
|
2280
|
-
return /* @__PURE__ */ React.createElement(AppContext.Provider, {
|
|
2281
|
-
value: versionedValue,
|
|
2282
|
-
children
|
|
2283
|
-
});
|
|
2275
|
+
return /* @__PURE__ */ React.createElement(AppContext.Provider, { value: versionedValue, children });
|
|
2284
2276
|
};
|
|
2285
2277
|
|
|
2286
2278
|
function mkError(thing) {
|
|
@@ -2355,7 +2347,7 @@ class AppIdentityProxy {
|
|
|
2355
2347
|
}
|
|
2356
2348
|
async signOut() {
|
|
2357
2349
|
await this.waitForTarget.then((target) => target.signOut());
|
|
2358
|
-
location.href = this.signOutTargetUrl;
|
|
2350
|
+
window.location.href = this.signOutTargetUrl;
|
|
2359
2351
|
}
|
|
2360
2352
|
}
|
|
2361
2353
|
|
|
@@ -2410,9 +2402,7 @@ function AppThemeProvider({ children }) {
|
|
|
2410
2402
|
if (!appTheme) {
|
|
2411
2403
|
throw new Error("App has no themes");
|
|
2412
2404
|
}
|
|
2413
|
-
return /* @__PURE__ */ React.createElement(appTheme.Provider, {
|
|
2414
|
-
children
|
|
2415
|
-
});
|
|
2405
|
+
return /* @__PURE__ */ React.createElement(appTheme.Provider, { children });
|
|
2416
2406
|
}
|
|
2417
2407
|
|
|
2418
2408
|
const defaultConfigLoader = async (runtimeConfigJson = "__APP_INJECTED_RUNTIME_CONFIG__") => {
|
|
@@ -2504,10 +2494,7 @@ function resolveRouteBindings(bindRoutes) {
|
|
|
2504
2494
|
}
|
|
2505
2495
|
|
|
2506
2496
|
function isReactRouterBeta() {
|
|
2507
|
-
const [obj] = createRoutesFromChildren(/* @__PURE__ */ React.createElement(Route, {
|
|
2508
|
-
index: true,
|
|
2509
|
-
element: /* @__PURE__ */ React.createElement("div", null)
|
|
2510
|
-
}));
|
|
2497
|
+
const [obj] = createRoutesFromChildren(/* @__PURE__ */ React.createElement(Route, { index: true, element: /* @__PURE__ */ React.createElement("div", null) }));
|
|
2511
2498
|
return !obj.index;
|
|
2512
2499
|
}
|
|
2513
2500
|
|
|
@@ -2522,7 +2509,7 @@ function readBasePath(configApi) {
|
|
|
2522
2509
|
var _a;
|
|
2523
2510
|
let { pathname } = new URL(
|
|
2524
2511
|
(_a = configApi.getOptionalString("app.baseUrl")) != null ? _a : "/",
|
|
2525
|
-
"http://
|
|
2512
|
+
"http://sample.dev"
|
|
2526
2513
|
);
|
|
2527
2514
|
pathname = pathname.replace(/\/*$/, "");
|
|
2528
2515
|
return pathname;
|
|
@@ -2537,20 +2524,52 @@ function useConfigLoader(configLoader, components, appThemeApi) {
|
|
|
2537
2524
|
noConfigNode = /* @__PURE__ */ React.createElement(Progress, null);
|
|
2538
2525
|
} else if (config.error) {
|
|
2539
2526
|
const { BootErrorPage } = components;
|
|
2540
|
-
noConfigNode = /* @__PURE__ */ React.createElement(BootErrorPage, {
|
|
2541
|
-
step: "load-config",
|
|
2542
|
-
error: config.error
|
|
2543
|
-
});
|
|
2527
|
+
noConfigNode = /* @__PURE__ */ React.createElement(BootErrorPage, { step: "load-config", error: config.error });
|
|
2544
2528
|
}
|
|
2545
2529
|
const { ThemeProvider = AppThemeProvider } = components;
|
|
2546
2530
|
if (noConfigNode) {
|
|
2547
2531
|
return {
|
|
2548
|
-
node: /* @__PURE__ */ React.createElement(ApiProvider, {
|
|
2549
|
-
apis: ApiRegistry.with(appThemeApiRef, appThemeApi)
|
|
2550
|
-
}, /* @__PURE__ */ React.createElement(ThemeProvider, null, noConfigNode))
|
|
2532
|
+
node: /* @__PURE__ */ React.createElement(ApiProvider, { apis: ApiRegistry.with(appThemeApiRef, appThemeApi) }, /* @__PURE__ */ React.createElement(ThemeProvider, null, noConfigNode))
|
|
2551
2533
|
};
|
|
2552
2534
|
}
|
|
2553
|
-
|
|
2535
|
+
let configReader;
|
|
2536
|
+
if ((_a = config.value) == null ? void 0 : _a.length) {
|
|
2537
|
+
const urlConfigReader = ConfigReader.fromConfigs(config.value);
|
|
2538
|
+
const getOrigin = (url) => new URL(url).origin;
|
|
2539
|
+
const overrideOrigin = (fullUrl) => {
|
|
2540
|
+
return new URL(
|
|
2541
|
+
fullUrl.replace(getOrigin(fullUrl), ""),
|
|
2542
|
+
document.location.origin
|
|
2543
|
+
).href;
|
|
2544
|
+
};
|
|
2545
|
+
const appBaseUrl = urlConfigReader.getOptionalString("app.baseUrl");
|
|
2546
|
+
const backendBaseUrl = urlConfigReader.getOptionalString("backend.baseUrl");
|
|
2547
|
+
let configs = config.value;
|
|
2548
|
+
const relativeResolverConfig = {
|
|
2549
|
+
data: {},
|
|
2550
|
+
context: "relative-resolver"
|
|
2551
|
+
};
|
|
2552
|
+
if (appBaseUrl && backendBaseUrl) {
|
|
2553
|
+
const appOrigin = getOrigin(appBaseUrl);
|
|
2554
|
+
const backendOrigin = getOrigin(backendBaseUrl);
|
|
2555
|
+
if (appOrigin === backendOrigin) {
|
|
2556
|
+
relativeResolverConfig.data.backend = {
|
|
2557
|
+
baseUrl: overrideOrigin(backendBaseUrl)
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
if (appBaseUrl) {
|
|
2562
|
+
relativeResolverConfig.data.app = {
|
|
2563
|
+
baseUrl: overrideOrigin(appBaseUrl)
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
if (Object.keys(relativeResolverConfig.data).length) {
|
|
2567
|
+
configs = configs.concat([relativeResolverConfig]);
|
|
2568
|
+
}
|
|
2569
|
+
configReader = ConfigReader.fromConfigs(configs);
|
|
2570
|
+
} else {
|
|
2571
|
+
configReader = ConfigReader.fromConfigs([]);
|
|
2572
|
+
}
|
|
2554
2573
|
return { api: configReader };
|
|
2555
2574
|
}
|
|
2556
2575
|
class AppContextImpl {
|
|
@@ -2600,6 +2619,7 @@ class AppManager {
|
|
|
2600
2619
|
const appContext = new AppContextImpl(this);
|
|
2601
2620
|
let routesHaveBeenValidated = false;
|
|
2602
2621
|
const Provider = ({ children }) => {
|
|
2622
|
+
const needsFeatureFlagRegistrationRef = useRef(true);
|
|
2603
2623
|
const appThemeApi = useMemo(
|
|
2604
2624
|
() => AppThemeSelector.createWithStorage(this.themes),
|
|
2605
2625
|
[]
|
|
@@ -2640,9 +2660,13 @@ class AppManager {
|
|
|
2640
2660
|
const { api } = loadedConfig;
|
|
2641
2661
|
this.configApi = api;
|
|
2642
2662
|
}
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2663
|
+
if ("node" in loadedConfig) {
|
|
2664
|
+
return loadedConfig.node;
|
|
2665
|
+
}
|
|
2666
|
+
if (hasConfigApi && needsFeatureFlagRegistrationRef.current) {
|
|
2667
|
+
needsFeatureFlagRegistrationRef.current = false;
|
|
2668
|
+
const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef);
|
|
2669
|
+
if (featureFlagsApi) {
|
|
2646
2670
|
for (const plugin of this.plugins.values()) {
|
|
2647
2671
|
if ("getFeatureFlags" in plugin) {
|
|
2648
2672
|
for (const flag of plugin.getFeatureFlags()) {
|
|
@@ -2662,28 +2686,33 @@ class AppManager {
|
|
|
2662
2686
|
}
|
|
2663
2687
|
}
|
|
2664
2688
|
}
|
|
2689
|
+
const registeredFlags = featureFlagsApi.getRegisteredFlags();
|
|
2690
|
+
const flagNames = new Set(registeredFlags.map((f) => f.name));
|
|
2665
2691
|
for (const name of featureFlags) {
|
|
2666
|
-
|
|
2692
|
+
if (!flagNames.has(name)) {
|
|
2693
|
+
featureFlagsApi.registerFlag({ name, pluginId: "" });
|
|
2694
|
+
}
|
|
2667
2695
|
}
|
|
2668
2696
|
}
|
|
2669
|
-
}, [hasConfigApi, loadedConfig, featureFlags]);
|
|
2670
|
-
if ("node" in loadedConfig) {
|
|
2671
|
-
return loadedConfig.node;
|
|
2672
2697
|
}
|
|
2673
2698
|
const { ThemeProvider = AppThemeProvider } = this.components;
|
|
2674
|
-
return /* @__PURE__ */ React.createElement(ApiProvider, {
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2699
|
+
return /* @__PURE__ */ React.createElement(ApiProvider, { apis: this.getApiHolder() }, /* @__PURE__ */ React.createElement(AppContextProvider, { appContext }, /* @__PURE__ */ React.createElement(ThemeProvider, null, /* @__PURE__ */ React.createElement(
|
|
2700
|
+
RoutingProvider,
|
|
2701
|
+
{
|
|
2702
|
+
routePaths: routing.paths,
|
|
2703
|
+
routeParents: routing.parents,
|
|
2704
|
+
routeObjects: routing.objects,
|
|
2705
|
+
routeBindings,
|
|
2706
|
+
basePath: getBasePath(loadedConfig.api)
|
|
2707
|
+
},
|
|
2708
|
+
/* @__PURE__ */ React.createElement(
|
|
2709
|
+
InternalAppContext.Provider,
|
|
2710
|
+
{
|
|
2711
|
+
value: { routeObjects: routing.objects }
|
|
2712
|
+
},
|
|
2713
|
+
children
|
|
2714
|
+
)
|
|
2715
|
+
))));
|
|
2687
2716
|
};
|
|
2688
2717
|
return Provider;
|
|
2689
2718
|
}
|
|
@@ -2697,9 +2726,7 @@ class AppManager {
|
|
|
2697
2726
|
const configApi = useApi(configApiRef);
|
|
2698
2727
|
const basePath = getBasePath(configApi);
|
|
2699
2728
|
if (!identityApi) {
|
|
2700
|
-
return /* @__PURE__ */ React.createElement(Component, {
|
|
2701
|
-
onSignInSuccess: setIdentityApi
|
|
2702
|
-
});
|
|
2729
|
+
return /* @__PURE__ */ React.createElement(Component, { onSignInSuccess: setIdentityApi });
|
|
2703
2730
|
}
|
|
2704
2731
|
this.appIdentityProxy.setTarget(identityApi, {
|
|
2705
2732
|
signOutTargetUrl: basePath || "/"
|
|
@@ -2736,36 +2763,14 @@ class AppManager {
|
|
|
2736
2763
|
{ signOutTargetUrl: basePath || "/" }
|
|
2737
2764
|
);
|
|
2738
2765
|
if (isReactRouterBeta()) {
|
|
2739
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, null, /* @__PURE__ */ React.createElement(RouteTracker, {
|
|
2740
|
-
routeObjects
|
|
2741
|
-
}), /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
2742
|
-
path: mountPath,
|
|
2743
|
-
element: /* @__PURE__ */ React.createElement(React.Fragment, null, children)
|
|
2744
|
-
})));
|
|
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) })));
|
|
2745
2767
|
}
|
|
2746
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, {
|
|
2747
|
-
basename: basePath
|
|
2748
|
-
}, /* @__PURE__ */ React.createElement(RouteTracker, {
|
|
2749
|
-
routeObjects
|
|
2750
|
-
}), children);
|
|
2768
|
+
return /* @__PURE__ */ React.createElement(RouterComponent, { basename: basePath }, /* @__PURE__ */ React.createElement(RouteTracker, { routeObjects }), children);
|
|
2751
2769
|
}
|
|
2752
2770
|
if (isReactRouterBeta()) {
|
|
2753
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, null, /* @__PURE__ */ React.createElement(RouteTracker, {
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
component: SignInPageComponent
|
|
2757
|
-
}, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
2758
|
-
path: mountPath,
|
|
2759
|
-
element: /* @__PURE__ */ React.createElement(React.Fragment, null, children)
|
|
2760
|
-
}))));
|
|
2761
|
-
}
|
|
2762
|
-
return /* @__PURE__ */ React.createElement(RouterComponent, {
|
|
2763
|
-
basename: basePath
|
|
2764
|
-
}, /* @__PURE__ */ React.createElement(RouteTracker, {
|
|
2765
|
-
routeObjects
|
|
2766
|
-
}), /* @__PURE__ */ React.createElement(SignInPageWrapper, {
|
|
2767
|
-
component: SignInPageComponent
|
|
2768
|
-
}, /* @__PURE__ */ React.createElement(React.Fragment, null, children)));
|
|
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)));
|
|
2769
2774
|
};
|
|
2770
2775
|
return AppRouter;
|
|
2771
2776
|
}
|