@backstage/frontend-app-api 0.6.4-next.1 → 0.6.5-next.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 +34 -0
- package/dist/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js +53 -0
- package/dist/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js.map +1 -0
- package/dist/apis/implementations/IconsApi/DefaultIconsApi.esm.js +35 -0
- package/dist/apis/implementations/IconsApi/DefaultIconsApi.esm.js.map +1 -0
- package/dist/app/src/components/Root/LogoFull.esm.js +33 -0
- package/dist/app/src/components/Root/LogoFull.esm.js.map +1 -0
- package/dist/app/src/components/Root/LogoIcon.esm.js +33 -0
- package/dist/app/src/components/Root/LogoIcon.esm.js.map +1 -0
- package/dist/app-defaults/src/defaults/apis.esm.js +221 -0
- package/dist/app-defaults/src/defaults/apis.esm.js.map +1 -0
- package/dist/app-defaults/src/defaults/components.esm.js +46 -0
- package/dist/app-defaults/src/defaults/components.esm.js.map +1 -0
- package/dist/app-defaults/src/defaults/icons.esm.js +51 -0
- package/dist/app-defaults/src/defaults/icons.esm.js.map +1 -0
- package/dist/core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js +114 -0
- package/dist/core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js.map +1 -0
- package/dist/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js +84 -0
- package/dist/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js.map +1 -0
- package/dist/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.esm.js +128 -0
- package/dist/core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.esm.js.map +1 -0
- package/dist/core-app-api/src/apis/implementations/IdentityApi/startCookieAuthRefresh.esm.js +105 -0
- package/dist/core-app-api/src/apis/implementations/IdentityApi/startCookieAuthRefresh.esm.js.map +1 -0
- package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js +275 -0
- package/dist/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js.map +1 -0
- package/dist/core-app-api/src/app/AppThemeProvider.esm.js +60 -0
- package/dist/core-app-api/src/app/AppThemeProvider.esm.js.map +1 -0
- package/dist/core-app-api/src/app/defaultConfigLoader.esm.js +33 -0
- package/dist/core-app-api/src/app/defaultConfigLoader.esm.js.map +1 -0
- package/dist/core-app-api/src/app/isProtectedApp.esm.js +9 -0
- package/dist/core-app-api/src/app/isProtectedApp.esm.js.map +1 -0
- package/dist/core-app-api/src/app/overrideBaseUrlConfigs.esm.js +50 -0
- package/dist/core-app-api/src/app/overrideBaseUrlConfigs.esm.js.map +1 -0
- package/dist/core-app-api/src/lib/subjects.esm.js +75 -0
- package/dist/core-app-api/src/lib/subjects.esm.js.map +1 -0
- package/dist/core-plugin-api/src/translation/TranslationRef.esm.js +13 -0
- package/dist/core-plugin-api/src/translation/TranslationRef.esm.js.map +1 -0
- package/dist/core-plugin-api/src/translation/TranslationResource.esm.js +13 -0
- package/dist/core-plugin-api/src/translation/TranslationResource.esm.js.map +1 -0
- package/dist/extensions/App.esm.js +39 -0
- package/dist/extensions/App.esm.js.map +1 -0
- package/dist/extensions/AppLayout.esm.js +34 -0
- package/dist/extensions/AppLayout.esm.js.map +1 -0
- package/dist/extensions/AppNav.esm.js +63 -0
- package/dist/extensions/AppNav.esm.js.map +1 -0
- package/dist/extensions/AppRoot.esm.js +125 -0
- package/dist/extensions/AppRoot.esm.js.map +1 -0
- package/dist/extensions/AppRoutes.esm.js +43 -0
- package/dist/extensions/AppRoutes.esm.js.map +1 -0
- package/dist/extensions/components.esm.js +52 -0
- package/dist/extensions/components.esm.js.map +1 -0
- package/dist/extensions/elements.esm.js +26 -0
- package/dist/extensions/elements.esm.js.map +1 -0
- package/dist/extensions/themes.esm.js +23 -0
- package/dist/extensions/themes.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/routing/ExternalRouteRef.esm.js +13 -0
- package/dist/frontend-plugin-api/src/routing/ExternalRouteRef.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/routing/RouteRef.esm.js +13 -0
- package/dist/frontend-plugin-api/src/routing/RouteRef.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/routing/SubRouteRef.esm.js +13 -0
- package/dist/frontend-plugin-api/src/routing/SubRouteRef.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/wiring/createExtension.esm.js +17 -0
- package/dist/frontend-plugin-api/src/wiring/createExtension.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/wiring/createExtensionOverrides.esm.js +17 -0
- package/dist/frontend-plugin-api/src/wiring/createExtensionOverrides.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/wiring/createPlugin.esm.js +15 -0
- package/dist/frontend-plugin-api/src/wiring/createPlugin.esm.js.map +1 -0
- package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js +41 -0
- package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js.map +1 -0
- package/dist/index.esm.js +1 -3029
- package/dist/index.esm.js.map +1 -1
- package/dist/routing/RouteResolver.esm.js +133 -0
- package/dist/routing/RouteResolver.esm.js.map +1 -0
- package/dist/routing/RouteTracker.esm.js +73 -0
- package/dist/routing/RouteTracker.esm.js.map +1 -0
- package/dist/routing/collectRouteIds.esm.js +40 -0
- package/dist/routing/collectRouteIds.esm.js.map +1 -0
- package/dist/routing/extractRouteInfoFromAppNode.esm.js +85 -0
- package/dist/routing/extractRouteInfoFromAppNode.esm.js.map +1 -0
- package/dist/routing/getBasePath.esm.js +13 -0
- package/dist/routing/getBasePath.esm.js.map +1 -0
- package/dist/routing/resolveRouteBindings.esm.js +66 -0
- package/dist/routing/resolveRouteBindings.esm.js.map +1 -0
- package/dist/routing/toLegacyPlugin.esm.js +35 -0
- package/dist/routing/toLegacyPlugin.esm.js.map +1 -0
- package/dist/tree/createAppTree.esm.js +21 -0
- package/dist/tree/createAppTree.esm.js.map +1 -0
- package/dist/tree/instantiateAppNodeTree.esm.js +146 -0
- package/dist/tree/instantiateAppNodeTree.esm.js.map +1 -0
- package/dist/tree/readAppExtensionsConfig.esm.js +106 -0
- package/dist/tree/readAppExtensionsConfig.esm.js.map +1 -0
- package/dist/tree/resolveAppNodeSpecs.esm.js +168 -0
- package/dist/tree/resolveAppNodeSpecs.esm.js.map +1 -0
- package/dist/tree/resolveAppTree.esm.js +97 -0
- package/dist/tree/resolveAppTree.esm.js.map +1 -0
- package/dist/wiring/InternalAppContext.esm.js +6 -0
- package/dist/wiring/InternalAppContext.esm.js.map +1 -0
- package/dist/wiring/createApp.esm.js +285 -0
- package/dist/wiring/createApp.esm.js.map +1 -0
- package/dist/wiring/discovery.esm.js +56 -0
- package/dist/wiring/discovery.esm.js.map +1 -0
- package/package.json +10 -10
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ConfigReader } from '@backstage/config';
|
|
3
|
+
import { createApiExtension, coreExtensionData, createThemeExtension, createTranslationExtension, appTreeApiRef, routeResolutionApiRef, componentsApiRef, iconsApiRef } from '@backstage/frontend-plugin-api';
|
|
4
|
+
import { App } from '../extensions/App.esm.js';
|
|
5
|
+
import { AppRoutes } from '../extensions/AppRoutes.esm.js';
|
|
6
|
+
import { AppLayout } from '../extensions/AppLayout.esm.js';
|
|
7
|
+
import { AppNav } from '../extensions/AppNav.esm.js';
|
|
8
|
+
import { discoveryApiRef, errorApiRef, fetchApiRef, featureFlagsApiRef, identityApiRef, appThemeApiRef, configApiRef } from '@backstage/core-plugin-api';
|
|
9
|
+
import { getAvailableFeatures } from './discovery.esm.js';
|
|
10
|
+
import { ApiFactoryRegistry, AppThemeSelector, ApiResolver, ApiProvider } from '@backstage/core-app-api';
|
|
11
|
+
import { isProtectedApp } from '../core-app-api/src/app/isProtectedApp.esm.js';
|
|
12
|
+
import { AppThemeProvider } from '../core-app-api/src/app/AppThemeProvider.esm.js';
|
|
13
|
+
import { AppIdentityProxy } from '../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy.esm.js';
|
|
14
|
+
import { LocalStorageFeatureFlags } from '../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.esm.js';
|
|
15
|
+
import { defaultConfigLoaderSync } from '../core-app-api/src/app/defaultConfigLoader.esm.js';
|
|
16
|
+
import { overrideBaseUrlConfigs } from '../core-app-api/src/app/overrideBaseUrlConfigs.esm.js';
|
|
17
|
+
import { AppLanguageSelector } from '../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector.esm.js';
|
|
18
|
+
import { I18nextTranslationApi } from '../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.esm.js';
|
|
19
|
+
import { resolveExtensionDefinition } from '../frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js';
|
|
20
|
+
import { apis } from '../app-defaults/src/defaults/apis.esm.js';
|
|
21
|
+
import '@material-ui/core/Button';
|
|
22
|
+
import '@backstage/core-components';
|
|
23
|
+
import 'react-router-dom';
|
|
24
|
+
import { icons } from '../app-defaults/src/defaults/icons.esm.js';
|
|
25
|
+
import '@backstage/theme';
|
|
26
|
+
import '@material-ui/icons/Brightness2';
|
|
27
|
+
import '@material-ui/icons/WbSunny';
|
|
28
|
+
import { LightTheme, DarkTheme } from '../extensions/themes.esm.js';
|
|
29
|
+
import { oauthRequestDialogAppRootElement, alertDisplayAppRootElement } from '../extensions/elements.esm.js';
|
|
30
|
+
import { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode.esm.js';
|
|
31
|
+
import { appLanguageApiRef, translationApiRef } from '@backstage/core-plugin-api/alpha';
|
|
32
|
+
import { RouteResolver } from '../routing/RouteResolver.esm.js';
|
|
33
|
+
import { resolveRouteBindings } from '../routing/resolveRouteBindings.esm.js';
|
|
34
|
+
import { collectRouteIds } from '../routing/collectRouteIds.esm.js';
|
|
35
|
+
import { createAppTree } from '../tree/createAppTree.esm.js';
|
|
36
|
+
import { DefaultProgressComponent, DefaultErrorBoundaryComponent, DefaultNotFoundErrorPageComponent } from '../extensions/components.esm.js';
|
|
37
|
+
import { InternalAppContext } from './InternalAppContext.esm.js';
|
|
38
|
+
import { AppRoot } from '../extensions/AppRoot.esm.js';
|
|
39
|
+
import { toInternalBackstagePlugin } from '../frontend-plugin-api/src/wiring/createPlugin.esm.js';
|
|
40
|
+
import { toInternalExtensionOverrides } from '../frontend-plugin-api/src/wiring/createExtensionOverrides.esm.js';
|
|
41
|
+
import { DefaultComponentsApi } from '../apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js';
|
|
42
|
+
import { DefaultIconsApi } from '../apis/implementations/IconsApi/DefaultIconsApi.esm.js';
|
|
43
|
+
import { stringifyError } from '@backstage/errors';
|
|
44
|
+
import { getBasePath } from '../routing/getBasePath.esm.js';
|
|
45
|
+
|
|
46
|
+
const DefaultApis = apis.map((factory) => createApiExtension({ factory }));
|
|
47
|
+
const builtinExtensions = [
|
|
48
|
+
App,
|
|
49
|
+
AppRoot,
|
|
50
|
+
AppRoutes,
|
|
51
|
+
AppNav,
|
|
52
|
+
AppLayout,
|
|
53
|
+
DefaultProgressComponent,
|
|
54
|
+
DefaultErrorBoundaryComponent,
|
|
55
|
+
DefaultNotFoundErrorPageComponent,
|
|
56
|
+
LightTheme,
|
|
57
|
+
DarkTheme,
|
|
58
|
+
oauthRequestDialogAppRootElement,
|
|
59
|
+
alertDisplayAppRootElement,
|
|
60
|
+
...DefaultApis
|
|
61
|
+
].map((def) => resolveExtensionDefinition(def));
|
|
62
|
+
function deduplicateFeatures(allFeatures) {
|
|
63
|
+
const features = Array.from(new Set(allFeatures));
|
|
64
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
65
|
+
return features.reverse().filter((feature) => {
|
|
66
|
+
if (feature.$$type !== "@backstage/BackstagePlugin") {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (seenIds.has(feature.id)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
seenIds.add(feature.id);
|
|
73
|
+
return true;
|
|
74
|
+
}).reverse();
|
|
75
|
+
}
|
|
76
|
+
function createApp(options) {
|
|
77
|
+
let suspenseFallback = options == null ? void 0 : options.loadingComponent;
|
|
78
|
+
if (suspenseFallback === void 0) {
|
|
79
|
+
suspenseFallback = "Loading...";
|
|
80
|
+
}
|
|
81
|
+
async function appLoader() {
|
|
82
|
+
var _a, _b, _c;
|
|
83
|
+
const config = (_b = await ((_a = options == null ? void 0 : options.configLoader) == null ? void 0 : _a.call(options).then((c) => c.config))) != null ? _b : ConfigReader.fromConfigs(
|
|
84
|
+
overrideBaseUrlConfigs(defaultConfigLoaderSync())
|
|
85
|
+
);
|
|
86
|
+
const discoveredFeatures = getAvailableFeatures(config);
|
|
87
|
+
const providedFeatures = [];
|
|
88
|
+
for (const entry of (_c = options == null ? void 0 : options.features) != null ? _c : []) {
|
|
89
|
+
if ("load" in entry) {
|
|
90
|
+
try {
|
|
91
|
+
const result = await entry.load({ config });
|
|
92
|
+
providedFeatures.push(...result.features);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Failed to read frontend features from loader '${entry.getLoaderName()}', ${stringifyError(
|
|
96
|
+
e
|
|
97
|
+
)}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
providedFeatures.push(entry);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const app = createSpecializedApp({
|
|
105
|
+
icons: options == null ? void 0 : options.icons,
|
|
106
|
+
config,
|
|
107
|
+
features: [...discoveredFeatures, ...providedFeatures],
|
|
108
|
+
bindRoutes: options == null ? void 0 : options.bindRoutes
|
|
109
|
+
}).createRoot();
|
|
110
|
+
return { default: () => app };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
createRoot() {
|
|
114
|
+
const LazyApp = React.lazy(appLoader);
|
|
115
|
+
return /* @__PURE__ */ React.createElement(React.Suspense, { fallback: suspenseFallback }, /* @__PURE__ */ React.createElement(LazyApp, null));
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function createSpecializedApp(options) {
|
|
120
|
+
const {
|
|
121
|
+
features: duplicatedFeatures = [],
|
|
122
|
+
config = new ConfigReader({}, "empty-config")
|
|
123
|
+
} = options != null ? options : {};
|
|
124
|
+
const features = deduplicateFeatures(duplicatedFeatures);
|
|
125
|
+
const tree = createAppTree({
|
|
126
|
+
features,
|
|
127
|
+
builtinExtensions,
|
|
128
|
+
config
|
|
129
|
+
});
|
|
130
|
+
const routeInfo = extractRouteInfoFromAppNode(tree.root);
|
|
131
|
+
const routeBindings = resolveRouteBindings(
|
|
132
|
+
options == null ? void 0 : options.bindRoutes,
|
|
133
|
+
config,
|
|
134
|
+
collectRouteIds(features)
|
|
135
|
+
);
|
|
136
|
+
const appIdentityProxy = new AppIdentityProxy();
|
|
137
|
+
const apiHolder = createApiHolder(
|
|
138
|
+
tree,
|
|
139
|
+
config,
|
|
140
|
+
appIdentityProxy,
|
|
141
|
+
new RouteResolver(
|
|
142
|
+
routeInfo.routePaths,
|
|
143
|
+
routeInfo.routeParents,
|
|
144
|
+
routeInfo.routeObjects,
|
|
145
|
+
routeBindings,
|
|
146
|
+
getBasePath(config)
|
|
147
|
+
),
|
|
148
|
+
options == null ? void 0 : options.icons
|
|
149
|
+
);
|
|
150
|
+
if (isProtectedApp()) {
|
|
151
|
+
const discoveryApi = apiHolder.get(discoveryApiRef);
|
|
152
|
+
const errorApi = apiHolder.get(errorApiRef);
|
|
153
|
+
const fetchApi = apiHolder.get(fetchApiRef);
|
|
154
|
+
if (!discoveryApi || !errorApi || !fetchApi) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
"App is running in protected mode but missing required APIs"
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
appIdentityProxy.enableCookieAuth({
|
|
160
|
+
discoveryApi,
|
|
161
|
+
errorApi,
|
|
162
|
+
fetchApi
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const featureFlagApi = apiHolder.get(featureFlagsApiRef);
|
|
166
|
+
if (featureFlagApi) {
|
|
167
|
+
for (const feature of features) {
|
|
168
|
+
if (feature.$$type === "@backstage/BackstagePlugin") {
|
|
169
|
+
toInternalBackstagePlugin(feature).featureFlags.forEach(
|
|
170
|
+
(flag) => featureFlagApi.registerFlag({
|
|
171
|
+
name: flag.name,
|
|
172
|
+
pluginId: feature.id
|
|
173
|
+
})
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
if (feature.$$type === "@backstage/ExtensionOverrides") {
|
|
177
|
+
toInternalExtensionOverrides(feature).featureFlags.forEach(
|
|
178
|
+
(flag) => featureFlagApi.registerFlag({ name: flag.name, pluginId: "" })
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const rootEl = tree.root.instance.getData(coreExtensionData.reactElement);
|
|
184
|
+
const AppComponent = () => /* @__PURE__ */ React.createElement(ApiProvider, { apis: apiHolder }, /* @__PURE__ */ React.createElement(AppThemeProvider, null, /* @__PURE__ */ React.createElement(
|
|
185
|
+
InternalAppContext.Provider,
|
|
186
|
+
{
|
|
187
|
+
value: { appIdentityProxy, routeObjects: routeInfo.routeObjects }
|
|
188
|
+
},
|
|
189
|
+
rootEl
|
|
190
|
+
)));
|
|
191
|
+
return {
|
|
192
|
+
createRoot() {
|
|
193
|
+
return /* @__PURE__ */ React.createElement(AppComponent, null);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function createApiHolder(tree, configApi, appIdentityProxy, routeResolutionApi, icons$1) {
|
|
198
|
+
var _a, _b, _c, _d, _e, _f;
|
|
199
|
+
const factoryRegistry = new ApiFactoryRegistry();
|
|
200
|
+
const pluginApis = (_b = (_a = tree.root.edges.attachments.get("apis")) == null ? void 0 : _a.map((e) => {
|
|
201
|
+
var _a2;
|
|
202
|
+
return (_a2 = e.instance) == null ? void 0 : _a2.getData(createApiExtension.factoryDataRef);
|
|
203
|
+
}).filter((x) => !!x)) != null ? _b : [];
|
|
204
|
+
const themeExtensions = (_d = (_c = tree.root.edges.attachments.get("themes")) == null ? void 0 : _c.map((e) => {
|
|
205
|
+
var _a2;
|
|
206
|
+
return (_a2 = e.instance) == null ? void 0 : _a2.getData(createThemeExtension.themeDataRef);
|
|
207
|
+
}).filter((x) => !!x)) != null ? _d : [];
|
|
208
|
+
const translationResources = (_f = (_e = tree.root.edges.attachments.get("translations")) == null ? void 0 : _e.map(
|
|
209
|
+
(e) => {
|
|
210
|
+
var _a2;
|
|
211
|
+
return (_a2 = e.instance) == null ? void 0 : _a2.getData(createTranslationExtension.translationDataRef);
|
|
212
|
+
}
|
|
213
|
+
).filter(
|
|
214
|
+
(x) => !!x
|
|
215
|
+
)) != null ? _f : [];
|
|
216
|
+
for (const factory of pluginApis) {
|
|
217
|
+
factoryRegistry.register("default", factory);
|
|
218
|
+
}
|
|
219
|
+
factoryRegistry.register("default", {
|
|
220
|
+
api: featureFlagsApiRef,
|
|
221
|
+
deps: {},
|
|
222
|
+
factory: () => new LocalStorageFeatureFlags()
|
|
223
|
+
});
|
|
224
|
+
factoryRegistry.register("static", {
|
|
225
|
+
api: identityApiRef,
|
|
226
|
+
deps: {},
|
|
227
|
+
factory: () => appIdentityProxy
|
|
228
|
+
});
|
|
229
|
+
factoryRegistry.register("static", {
|
|
230
|
+
api: appTreeApiRef,
|
|
231
|
+
deps: {},
|
|
232
|
+
factory: () => ({
|
|
233
|
+
getTree: () => ({ tree })
|
|
234
|
+
})
|
|
235
|
+
});
|
|
236
|
+
factoryRegistry.register("static", {
|
|
237
|
+
api: routeResolutionApiRef,
|
|
238
|
+
deps: {},
|
|
239
|
+
factory: () => routeResolutionApi
|
|
240
|
+
});
|
|
241
|
+
factoryRegistry.register("static", {
|
|
242
|
+
api: componentsApiRef,
|
|
243
|
+
deps: {},
|
|
244
|
+
factory: () => DefaultComponentsApi.fromTree(tree)
|
|
245
|
+
});
|
|
246
|
+
factoryRegistry.register("static", {
|
|
247
|
+
api: iconsApiRef,
|
|
248
|
+
deps: {},
|
|
249
|
+
factory: () => new DefaultIconsApi({ ...icons, ...icons$1 })
|
|
250
|
+
});
|
|
251
|
+
factoryRegistry.register("static", {
|
|
252
|
+
api: appThemeApiRef,
|
|
253
|
+
deps: {},
|
|
254
|
+
// TODO: add extension for registering themes
|
|
255
|
+
factory: () => AppThemeSelector.createWithStorage(themeExtensions)
|
|
256
|
+
});
|
|
257
|
+
factoryRegistry.register("static", {
|
|
258
|
+
api: appLanguageApiRef,
|
|
259
|
+
deps: {},
|
|
260
|
+
factory: () => AppLanguageSelector.createWithStorage()
|
|
261
|
+
});
|
|
262
|
+
factoryRegistry.register("static", {
|
|
263
|
+
api: configApiRef,
|
|
264
|
+
deps: {},
|
|
265
|
+
factory: () => configApi
|
|
266
|
+
});
|
|
267
|
+
factoryRegistry.register("static", {
|
|
268
|
+
api: appLanguageApiRef,
|
|
269
|
+
deps: {},
|
|
270
|
+
factory: () => AppLanguageSelector.createWithStorage()
|
|
271
|
+
});
|
|
272
|
+
factoryRegistry.register("static", {
|
|
273
|
+
api: translationApiRef,
|
|
274
|
+
deps: { languageApi: appLanguageApiRef },
|
|
275
|
+
factory: ({ languageApi }) => I18nextTranslationApi.create({
|
|
276
|
+
languageApi,
|
|
277
|
+
resources: translationResources
|
|
278
|
+
})
|
|
279
|
+
});
|
|
280
|
+
ApiResolver.validateFactories(factoryRegistry, factoryRegistry.getAllApis());
|
|
281
|
+
return new ApiResolver(factoryRegistry);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export { builtinExtensions, createApp, createSpecializedApp };
|
|
285
|
+
//# sourceMappingURL=createApp.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createApp.esm.js","sources":["../../src/wiring/createApp.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { JSX, ReactNode } from 'react';\nimport { ConfigReader } from '@backstage/config';\nimport {\n AppTree,\n appTreeApiRef,\n componentsApiRef,\n coreExtensionData,\n createApiExtension,\n createThemeExtension,\n createTranslationExtension,\n FrontendFeature,\n iconsApiRef,\n RouteResolutionApi,\n routeResolutionApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { App } from '../extensions/App';\nimport { AppRoutes } from '../extensions/AppRoutes';\nimport { AppLayout } from '../extensions/AppLayout';\nimport { AppNav } from '../extensions/AppNav';\nimport {\n AnyApiFactory,\n ApiHolder,\n appThemeApiRef,\n ConfigApi,\n configApiRef,\n IconComponent,\n featureFlagsApiRef,\n identityApiRef,\n AppTheme,\n errorApiRef,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport { getAvailableFeatures } from './discovery';\nimport {\n ApiFactoryRegistry,\n ApiProvider,\n ApiResolver,\n AppThemeSelector,\n} from '@backstage/core-app-api';\n\n// TODO: Get rid of all of these\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isProtectedApp } from '../../../core-app-api/src/app/isProtectedApp';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppThemeProvider } from '../../../core-app-api/src/app/AppThemeProvider';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultConfigLoader';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { overrideBaseUrlConfigs } from '../../../core-app-api/src/app/overrideBaseUrlConfigs';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { I18nextTranslationApi } from '../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { apis as defaultApis } from '../../../app-defaults/src/defaults';\nimport { DarkTheme, LightTheme } from '../extensions/themes';\nimport {\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n} from '../extensions/elements';\nimport { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode';\nimport {\n appLanguageApiRef,\n translationApiRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { CreateAppRouteBinder } from '../routing';\nimport { RouteResolver } from '../routing/RouteResolver';\nimport { resolveRouteBindings } from '../routing/resolveRouteBindings';\nimport { collectRouteIds } from '../routing/collectRouteIds';\nimport { createAppTree } from '../tree';\nimport {\n DefaultProgressComponent,\n DefaultErrorBoundaryComponent,\n DefaultNotFoundErrorPageComponent,\n} from '../extensions/components';\nimport { InternalAppContext } from './InternalAppContext';\nimport { AppRoot } from '../extensions/AppRoot';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createPlugin';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides';\nimport { DefaultComponentsApi } from '../apis/implementations/ComponentsApi';\nimport { DefaultIconsApi } from '../apis/implementations/IconsApi';\nimport { stringifyError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { icons as defaultIcons } from '../../../app-defaults/src/defaults';\nimport { getBasePath } from '../routing/getBasePath';\n\nconst DefaultApis = defaultApis.map(factory => createApiExtension({ factory }));\n\nexport const builtinExtensions = [\n App,\n AppRoot,\n AppRoutes,\n AppNav,\n AppLayout,\n DefaultProgressComponent,\n DefaultErrorBoundaryComponent,\n DefaultNotFoundErrorPageComponent,\n LightTheme,\n DarkTheme,\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n ...DefaultApis,\n].map(def => resolveExtensionDefinition(def));\n\nfunction deduplicateFeatures(\n allFeatures: FrontendFeature[],\n): FrontendFeature[] {\n // Start by removing duplicates by reference\n const features = Array.from(new Set(allFeatures));\n\n // Plugins are deduplicated by ID, last one wins\n const seenIds = new Set<string>();\n return features\n .reverse()\n .filter(feature => {\n if (feature.$$type !== '@backstage/BackstagePlugin') {\n return true;\n }\n if (seenIds.has(feature.id)) {\n return false;\n }\n seenIds.add(feature.id);\n return true;\n })\n .reverse();\n}\n\n/**\n * A source of dynamically loaded frontend features.\n *\n * @public\n */\nexport interface CreateAppFeatureLoader {\n /**\n * Returns name of this loader. suitable for showing to users.\n */\n getLoaderName(): string;\n\n /**\n * Loads a number of features dynamically.\n */\n load(options: { config: ConfigApi }): Promise<{\n features: FrontendFeature[];\n }>;\n}\n\n/** @public */\nexport function createApp(options?: {\n icons?: { [key in string]: IconComponent };\n features?: (FrontendFeature | CreateAppFeatureLoader)[];\n configLoader?: () => Promise<{ config: ConfigApi }>;\n bindRoutes?(context: { bind: CreateAppRouteBinder }): void;\n /**\n * The component to render while loading the app (waiting for config, features, etc)\n *\n * Is the text \"Loading...\" by default.\n * If set to \"null\" then no loading fallback component is rendered. *\n */\n loadingComponent?: ReactNode;\n}): {\n createRoot(): JSX.Element;\n} {\n let suspenseFallback = options?.loadingComponent;\n if (suspenseFallback === undefined) {\n suspenseFallback = 'Loading...';\n }\n\n async function appLoader() {\n const config =\n (await options?.configLoader?.().then(c => c.config)) ??\n ConfigReader.fromConfigs(\n overrideBaseUrlConfigs(defaultConfigLoaderSync()),\n );\n\n const discoveredFeatures = getAvailableFeatures(config);\n\n const providedFeatures: FrontendFeature[] = [];\n for (const entry of options?.features ?? []) {\n if ('load' in entry) {\n try {\n const result = await entry.load({ config });\n providedFeatures.push(...result.features);\n } catch (e) {\n throw new Error(\n `Failed to read frontend features from loader '${entry.getLoaderName()}', ${stringifyError(\n e,\n )}`,\n );\n }\n } else {\n providedFeatures.push(entry);\n }\n }\n\n const app = createSpecializedApp({\n icons: options?.icons,\n config,\n features: [...discoveredFeatures, ...providedFeatures],\n bindRoutes: options?.bindRoutes,\n }).createRoot();\n\n return { default: () => app };\n }\n\n return {\n createRoot() {\n const LazyApp = React.lazy(appLoader);\n return (\n <React.Suspense fallback={suspenseFallback}>\n <LazyApp />\n </React.Suspense>\n );\n },\n };\n}\n\n/**\n * Synchronous version of {@link createApp}, expecting all features and\n * config to have been loaded already.\n *\n * @public\n */\nexport function createSpecializedApp(options?: {\n icons?: { [key in string]: IconComponent };\n features?: FrontendFeature[];\n config?: ConfigApi;\n bindRoutes?(context: { bind: CreateAppRouteBinder }): void;\n}): { createRoot(): JSX.Element } {\n const {\n features: duplicatedFeatures = [],\n config = new ConfigReader({}, 'empty-config'),\n } = options ?? {};\n\n const features = deduplicateFeatures(duplicatedFeatures);\n\n const tree = createAppTree({\n features,\n builtinExtensions,\n config,\n });\n\n const routeInfo = extractRouteInfoFromAppNode(tree.root);\n const routeBindings = resolveRouteBindings(\n options?.bindRoutes,\n config,\n collectRouteIds(features),\n );\n\n const appIdentityProxy = new AppIdentityProxy();\n const apiHolder = createApiHolder(\n tree,\n config,\n appIdentityProxy,\n new RouteResolver(\n routeInfo.routePaths,\n routeInfo.routeParents,\n routeInfo.routeObjects,\n routeBindings,\n getBasePath(config),\n ),\n options?.icons,\n );\n\n if (isProtectedApp()) {\n const discoveryApi = apiHolder.get(discoveryApiRef);\n const errorApi = apiHolder.get(errorApiRef);\n const fetchApi = apiHolder.get(fetchApiRef);\n if (!discoveryApi || !errorApi || !fetchApi) {\n throw new Error(\n 'App is running in protected mode but missing required APIs',\n );\n }\n appIdentityProxy.enableCookieAuth({\n discoveryApi,\n errorApi,\n fetchApi,\n });\n }\n\n const featureFlagApi = apiHolder.get(featureFlagsApiRef);\n if (featureFlagApi) {\n for (const feature of features) {\n if (feature.$$type === '@backstage/BackstagePlugin') {\n toInternalBackstagePlugin(feature).featureFlags.forEach(flag =>\n featureFlagApi.registerFlag({\n name: flag.name,\n pluginId: feature.id,\n }),\n );\n }\n if (feature.$$type === '@backstage/ExtensionOverrides') {\n toInternalExtensionOverrides(feature).featureFlags.forEach(flag =>\n featureFlagApi.registerFlag({ name: flag.name, pluginId: '' }),\n );\n }\n }\n }\n\n const rootEl = tree.root.instance!.getData(coreExtensionData.reactElement);\n\n const AppComponent = () => (\n <ApiProvider apis={apiHolder}>\n <AppThemeProvider>\n <InternalAppContext.Provider\n value={{ appIdentityProxy, routeObjects: routeInfo.routeObjects }}\n >\n {rootEl}\n </InternalAppContext.Provider>\n </AppThemeProvider>\n </ApiProvider>\n );\n\n return {\n createRoot() {\n return <AppComponent />;\n },\n };\n}\n\nfunction createApiHolder(\n tree: AppTree,\n configApi: ConfigApi,\n appIdentityProxy: AppIdentityProxy,\n routeResolutionApi: RouteResolutionApi,\n icons?: { [key in string]: IconComponent },\n): ApiHolder {\n const factoryRegistry = new ApiFactoryRegistry();\n\n const pluginApis =\n tree.root.edges.attachments\n .get('apis')\n ?.map(e => e.instance?.getData(createApiExtension.factoryDataRef))\n .filter((x): x is AnyApiFactory => !!x) ?? [];\n\n const themeExtensions =\n tree.root.edges.attachments\n .get('themes')\n ?.map(e => e.instance?.getData(createThemeExtension.themeDataRef))\n .filter((x): x is AppTheme => !!x) ?? [];\n\n const translationResources =\n tree.root.edges.attachments\n .get('translations')\n ?.map(e =>\n e.instance?.getData(createTranslationExtension.translationDataRef),\n )\n .filter(\n (x): x is typeof createTranslationExtension.translationDataRef.T => !!x,\n ) ?? [];\n\n for (const factory of pluginApis) {\n factoryRegistry.register('default', factory);\n }\n\n // TODO: properly discovery feature flags, maybe rework the whole thing\n factoryRegistry.register('default', {\n api: featureFlagsApiRef,\n deps: {},\n factory: () => new LocalStorageFeatureFlags(),\n });\n\n factoryRegistry.register('static', {\n api: identityApiRef,\n deps: {},\n factory: () => appIdentityProxy,\n });\n\n factoryRegistry.register('static', {\n api: appTreeApiRef,\n deps: {},\n factory: () => ({\n getTree: () => ({ tree }),\n }),\n });\n\n factoryRegistry.register('static', {\n api: routeResolutionApiRef,\n deps: {},\n factory: () => routeResolutionApi,\n });\n\n factoryRegistry.register('static', {\n api: componentsApiRef,\n deps: {},\n factory: () => DefaultComponentsApi.fromTree(tree),\n });\n\n factoryRegistry.register('static', {\n api: iconsApiRef,\n deps: {},\n factory: () => new DefaultIconsApi({ ...defaultIcons, ...icons }),\n });\n\n factoryRegistry.register('static', {\n api: appThemeApiRef,\n deps: {},\n // TODO: add extension for registering themes\n factory: () => AppThemeSelector.createWithStorage(themeExtensions),\n });\n\n factoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => AppLanguageSelector.createWithStorage(),\n });\n\n factoryRegistry.register('static', {\n api: configApiRef,\n deps: {},\n factory: () => configApi,\n });\n\n factoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => AppLanguageSelector.createWithStorage(),\n });\n\n factoryRegistry.register('static', {\n api: translationApiRef,\n deps: { languageApi: appLanguageApiRef },\n factory: ({ languageApi }) =>\n I18nextTranslationApi.create({\n languageApi,\n resources: translationResources,\n }),\n });\n\n ApiResolver.validateFactories(factoryRegistry, factoryRegistry.getAllApis());\n\n return new ApiResolver(factoryRegistry);\n}\n"],"names":["defaultApis","icons","_a","defaultIcons"],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ConfigReader } from '@backstage/config';
|
|
2
|
+
|
|
3
|
+
function readPackageDetectionConfig(config) {
|
|
4
|
+
const packages = config.getOptional("app.experimental.packages");
|
|
5
|
+
if (packages === void 0 || packages === null) {
|
|
6
|
+
return void 0;
|
|
7
|
+
}
|
|
8
|
+
if (typeof packages === "string") {
|
|
9
|
+
if (packages !== "all") {
|
|
10
|
+
throw new Error(
|
|
11
|
+
`Invalid app.experimental.packages mode, got '${packages}', expected 'all'`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
if (typeof packages !== "object" || Array.isArray(packages)) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"Invalid config at 'app.experimental.packages', expected object"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
const packagesConfig = new ConfigReader(
|
|
22
|
+
packages,
|
|
23
|
+
"app.experimental.packages"
|
|
24
|
+
);
|
|
25
|
+
return {
|
|
26
|
+
include: packagesConfig.getOptionalStringArray("include"),
|
|
27
|
+
exclude: packagesConfig.getOptionalStringArray("exclude")
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function getAvailableFeatures(config) {
|
|
31
|
+
var _a;
|
|
32
|
+
const discovered = window["__@backstage/discovered__"];
|
|
33
|
+
const detection = readPackageDetectionConfig(config);
|
|
34
|
+
if (!detection) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return (_a = discovered == null ? void 0 : discovered.modules.filter(({ name }) => {
|
|
38
|
+
var _a2;
|
|
39
|
+
if ((_a2 = detection.exclude) == null ? void 0 : _a2.includes(name)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (detection.include && !detection.include.includes(name)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}).map((m) => m.default).filter(isBackstageFeature)) != null ? _a : [];
|
|
47
|
+
}
|
|
48
|
+
function isBackstageFeature(obj) {
|
|
49
|
+
if (obj !== null && typeof obj === "object" && "$$type" in obj) {
|
|
50
|
+
return obj.$$type === "@backstage/BackstagePlugin" || obj.$$type === "@backstage/ExtensionOverrides";
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { getAvailableFeatures };
|
|
56
|
+
//# sourceMappingURL=discovery.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.esm.js","sources":["../../src/wiring/discovery.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config, ConfigReader } from '@backstage/config';\nimport { FrontendFeature } from '@backstage/frontend-plugin-api';\n\ninterface DiscoveryGlobal {\n modules: Array<{ name: string; export?: string; default: unknown }>;\n}\n\nfunction readPackageDetectionConfig(config: Config) {\n const packages = config.getOptional('app.experimental.packages');\n if (packages === undefined || packages === null) {\n return undefined;\n }\n\n if (typeof packages === 'string') {\n if (packages !== 'all') {\n throw new Error(\n `Invalid app.experimental.packages mode, got '${packages}', expected 'all'`,\n );\n }\n return {};\n }\n\n if (typeof packages !== 'object' || Array.isArray(packages)) {\n throw new Error(\n \"Invalid config at 'app.experimental.packages', expected object\",\n );\n }\n const packagesConfig = new ConfigReader(\n packages,\n 'app.experimental.packages',\n );\n\n return {\n include: packagesConfig.getOptionalStringArray('include'),\n exclude: packagesConfig.getOptionalStringArray('exclude'),\n };\n}\n\n/**\n * @public\n */\nexport function getAvailableFeatures(config: Config): FrontendFeature[] {\n const discovered = (\n window as { '__@backstage/discovered__'?: DiscoveryGlobal }\n )['__@backstage/discovered__'];\n\n const detection = readPackageDetectionConfig(config);\n if (!detection) {\n return [];\n }\n\n return (\n discovered?.modules\n .filter(({ name }) => {\n if (detection.exclude?.includes(name)) {\n return false;\n }\n if (detection.include && !detection.include.includes(name)) {\n return false;\n }\n return true;\n })\n .map(m => m.default)\n .filter(isBackstageFeature) ?? []\n );\n}\n\nfunction isBackstageFeature(obj: unknown): obj is FrontendFeature {\n if (obj !== null && typeof obj === 'object' && '$$type' in obj) {\n return (\n obj.$$type === '@backstage/BackstagePlugin' ||\n obj.$$type === '@backstage/ExtensionOverrides'\n );\n }\n return false;\n}\n"],"names":["_a"],"mappings":";;AAuBA,SAAS,2BAA2B,MAAgB,EAAA;AAClD,EAAM,MAAA,QAAA,GAAW,MAAO,CAAA,WAAA,CAAY,2BAA2B,CAAA,CAAA;AAC/D,EAAI,IAAA,QAAA,KAAa,KAAa,CAAA,IAAA,QAAA,KAAa,IAAM,EAAA;AAC/C,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AAEA,EAAI,IAAA,OAAO,aAAa,QAAU,EAAA;AAChC,IAAA,IAAI,aAAa,KAAO,EAAA;AACtB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,gDAAgD,QAAQ,CAAA,iBAAA,CAAA;AAAA,OAC1D,CAAA;AAAA,KACF;AACA,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,IAAI,OAAO,QAAa,KAAA,QAAA,IAAY,KAAM,CAAA,OAAA,CAAQ,QAAQ,CAAG,EAAA;AAC3D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gEAAA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAA,MAAM,iBAAiB,IAAI,YAAA;AAAA,IACzB,QAAA;AAAA,IACA,2BAAA;AAAA,GACF,CAAA;AAEA,EAAO,OAAA;AAAA,IACL,OAAA,EAAS,cAAe,CAAA,sBAAA,CAAuB,SAAS,CAAA;AAAA,IACxD,OAAA,EAAS,cAAe,CAAA,sBAAA,CAAuB,SAAS,CAAA;AAAA,GAC1D,CAAA;AACF,CAAA;AAKO,SAAS,qBAAqB,MAAmC,EAAA;AAzDxE,EAAA,IAAA,EAAA,CAAA;AA0DE,EAAM,MAAA,UAAA,GACJ,OACA,2BAA2B,CAAA,CAAA;AAE7B,EAAM,MAAA,SAAA,GAAY,2BAA2B,MAAM,CAAA,CAAA;AACnD,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,OAAA,CACE,8CAAY,OACT,CAAA,MAAA,CAAO,CAAC,EAAE,MAAW,KAAA;AArE5B,IAAAA,IAAAA,GAAAA,CAAAA;AAsEQ,IAAA,IAAA,CAAIA,MAAA,SAAU,CAAA,OAAA,KAAV,IAAAA,GAAAA,KAAAA,CAAAA,GAAAA,GAAAA,CAAmB,SAAS,IAAO,CAAA,EAAA;AACrC,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AACA,IAAA,IAAI,UAAU,OAAW,IAAA,CAAC,UAAU,OAAQ,CAAA,QAAA,CAAS,IAAI,CAAG,EAAA;AAC1D,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AACA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT,CAAA,CACC,IAAI,CAAK,CAAA,KAAA,CAAA,CAAE,SACX,MAAO,CAAA,kBAAA,CAAA,KAXV,YAWiC,EAAC,CAAA;AAEtC,CAAA;AAEA,SAAS,mBAAmB,GAAsC,EAAA;AAChE,EAAA,IAAI,QAAQ,IAAQ,IAAA,OAAO,GAAQ,KAAA,QAAA,IAAY,YAAY,GAAK,EAAA;AAC9D,IAAA,OACE,GAAI,CAAA,MAAA,KAAW,4BACf,IAAA,GAAA,CAAI,MAAW,KAAA,+BAAA,CAAA;AAAA,GAEnB;AACA,EAAO,OAAA,KAAA,CAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/frontend-app-api",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5-next.0",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "web-library"
|
|
6
6
|
},
|
|
@@ -33,24 +33,24 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@backstage/config": "^1.2.0",
|
|
36
|
-
"@backstage/core-app-api": "^1.12.4
|
|
37
|
-
"@backstage/core-components": "^0.14.
|
|
38
|
-
"@backstage/core-plugin-api": "^1.9.
|
|
36
|
+
"@backstage/core-app-api": "^1.12.4",
|
|
37
|
+
"@backstage/core-components": "^0.14.5-next.0",
|
|
38
|
+
"@backstage/core-plugin-api": "^1.9.2",
|
|
39
39
|
"@backstage/errors": "^1.2.4",
|
|
40
|
-
"@backstage/frontend-plugin-api": "^0.6.
|
|
41
|
-
"@backstage/theme": "^0.5.
|
|
40
|
+
"@backstage/frontend-plugin-api": "^0.6.5-next.0",
|
|
41
|
+
"@backstage/theme": "^0.5.4-next.0",
|
|
42
42
|
"@backstage/types": "^1.1.1",
|
|
43
|
-
"@backstage/version-bridge": "^1.0.
|
|
43
|
+
"@backstage/version-bridge": "^1.0.8",
|
|
44
44
|
"@material-ui/core": "^4.12.4",
|
|
45
45
|
"@material-ui/icons": "^4.11.3",
|
|
46
46
|
"@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|
|
47
47
|
"lodash": "^4.17.21"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@backstage/cli": "^0.26.
|
|
51
|
-
"@backstage/test-utils": "^1.5.
|
|
50
|
+
"@backstage/cli": "^0.26.5-next.0",
|
|
51
|
+
"@backstage/test-utils": "^1.5.5-next.0",
|
|
52
52
|
"@testing-library/jest-dom": "^6.0.0",
|
|
53
|
-
"@testing-library/react": "^
|
|
53
|
+
"@testing-library/react": "^15.0.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|