frontend-app-api: remove experimental createExtensionTree API
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the experimental `createExtensionTree` API.
|
||||
@@ -27,12 +27,7 @@ import {
|
||||
RELATION_PROVIDES_API,
|
||||
} from '@backstage/catalog-model';
|
||||
import { createApp } from '@backstage/app-defaults';
|
||||
import {
|
||||
AppRouter,
|
||||
ConfigReader,
|
||||
defaultConfigLoader,
|
||||
FlatRoutes,
|
||||
} from '@backstage/core-app-api';
|
||||
import { AppRouter, FlatRoutes } from '@backstage/core-app-api';
|
||||
import {
|
||||
AlertDisplay,
|
||||
OAuthRequestDialog,
|
||||
@@ -112,10 +107,6 @@ import { PuppetDbPage } from '@backstage/plugin-puppetdb';
|
||||
import { DevToolsPage } from '@backstage/plugin-devtools';
|
||||
import { customDevToolsPage } from './components/devtools/CustomDevToolsPage';
|
||||
import { CatalogUnprocessedEntitiesPage } from '@backstage/plugin-catalog-unprocessed-entities';
|
||||
import {
|
||||
createExtensionTree,
|
||||
ExtensionTree,
|
||||
} from '@backstage/frontend-app-api';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
@@ -162,14 +153,6 @@ const app = createApp({
|
||||
},
|
||||
});
|
||||
|
||||
/* HIGHLY EXPERIMENTAL. DO NOT USE THIS IN YOUR APP */
|
||||
let extensionTree: ExtensionTree | undefined;
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
extensionTree = createExtensionTree({
|
||||
config: ConfigReader.fromConfigs(await defaultConfigLoader()),
|
||||
});
|
||||
}
|
||||
|
||||
const routes = (
|
||||
<FlatRoutes>
|
||||
<Route path="/" element={<Navigate to="catalog" />} />
|
||||
@@ -258,10 +241,6 @@ const routes = (
|
||||
path="/tech-radar"
|
||||
element={<TechRadarPage width={1500} height={800} />}
|
||||
/>
|
||||
{
|
||||
/* HIGHLY EXPERIMENTAL. DO NOT USE THIS IN YOUR APP */ extensionTree?.getRootRoutes() ??
|
||||
null
|
||||
}
|
||||
<Route path="/lighthouse" element={<LighthousePage />} />
|
||||
<Route path="/api-docs" element={<ApiExplorerPage />} />
|
||||
<Route path="/gcp-projects" element={<GcpProjectsPage />} />
|
||||
@@ -302,7 +281,7 @@ export default app.createRoot(
|
||||
<OAuthRequestDialog />
|
||||
<AppRouter>
|
||||
<VisitListener />
|
||||
<Root extensionTree={extensionTree}>{routes}</Root>
|
||||
<Root>{routes}</Root>
|
||||
</AppRouter>
|
||||
</>,
|
||||
);
|
||||
|
||||
@@ -84,7 +84,6 @@ const SidebarLogo = () => {
|
||||
|
||||
export const Root = ({
|
||||
children,
|
||||
extensionTree,
|
||||
}: PropsWithChildren<{ extensionTree?: ExtensionTree }>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
@@ -166,10 +165,6 @@ export const Root = ({
|
||||
to="cost-insights"
|
||||
text="Cost Insights"
|
||||
/>
|
||||
{
|
||||
/* HIGHLY EXPERIMENTAL. DO NOT USE THIS IN YOUR APP */ extensionTree?.getSidebarItems() ??
|
||||
null
|
||||
}
|
||||
<SidebarItem icon={Score} to="score-board" text="Score board" />
|
||||
</SidebarScrollWrapper>
|
||||
<SidebarDivider />
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { Config } from '@backstage/config';
|
||||
import { ConfigApi } from '@backstage/core-plugin-api';
|
||||
import { ExtensionDataRef } from '@backstage/frontend-plugin-api';
|
||||
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { FrontendFeature } from '@backstage/frontend-plugin-api';
|
||||
import { IconComponent } from '@backstage/core-plugin-api';
|
||||
@@ -48,9 +46,6 @@ export type CreateAppRouteBinder = <
|
||||
>,
|
||||
) => void;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createExtensionTree(options: { config: Config }): ExtensionTree;
|
||||
|
||||
// @public
|
||||
export function createSpecializedApp(options?: {
|
||||
icons?: {
|
||||
@@ -62,24 +57,4 @@ export function createSpecializedApp(options?: {
|
||||
}): {
|
||||
createRoot(): JSX_2.Element;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface ExtensionTree {
|
||||
// (undocumented)
|
||||
getExtension(id: string): ExtensionTreeNode | undefined;
|
||||
// (undocumented)
|
||||
getExtensionAttachments(id: string, inputName: string): ExtensionTreeNode[];
|
||||
// (undocumented)
|
||||
getRootRoutes(): JSX_2.Element[];
|
||||
// (undocumented)
|
||||
getSidebarItems(): JSX_2.Element[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface ExtensionTreeNode {
|
||||
// (undocumented)
|
||||
getData<T>(ref: ExtensionDataRef<T>): T | undefined;
|
||||
// (undocumented)
|
||||
id: string;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import React, { JSX } from 'react';
|
||||
import { ConfigReader, Config } from '@backstage/config';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
AppTree,
|
||||
appTreeApiRef,
|
||||
@@ -24,16 +24,12 @@ import {
|
||||
coreExtensionData,
|
||||
createApiExtension,
|
||||
createComponentExtension,
|
||||
createNavItemExtension,
|
||||
createThemeExtension,
|
||||
createTranslationExtension,
|
||||
ExtensionDataRef,
|
||||
FrontendFeature,
|
||||
iconsApiRef,
|
||||
RouteRef,
|
||||
RouteResolutionApi,
|
||||
routeResolutionApiRef,
|
||||
useRouteRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { App } from '../extensions/App';
|
||||
import { AppRoutes } from '../extensions/AppRoutes';
|
||||
@@ -47,7 +43,6 @@ import {
|
||||
configApiRef,
|
||||
IconComponent,
|
||||
featureFlagsApiRef,
|
||||
attachComponentData,
|
||||
identityApiRef,
|
||||
AppTheme,
|
||||
} from '@backstage/core-plugin-api';
|
||||
@@ -78,8 +73,6 @@ import { I18nextTranslationApi } from '../../../core-app-api/src/apis/implementa
|
||||
import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { apis as defaultApis } from '../../../app-defaults/src/defaults';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { SidebarItem } from '@backstage/core-components';
|
||||
import { DarkTheme, LightTheme } from '../extensions/themes';
|
||||
import {
|
||||
oauthRequestDialogAppRootElement,
|
||||
@@ -100,7 +93,6 @@ import {
|
||||
DefaultErrorBoundaryComponent,
|
||||
DefaultNotFoundErrorPageComponent,
|
||||
} from '../extensions/components';
|
||||
import { AppNode } from '@backstage/frontend-plugin-api';
|
||||
import { InternalAppContext } from './InternalAppContext';
|
||||
import { AppRoot } from '../extensions/AppRoot';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
@@ -132,106 +124,6 @@ export const builtinExtensions = [
|
||||
...DefaultApis,
|
||||
].map(def => resolveExtensionDefinition(def));
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionTreeNode {
|
||||
id: string;
|
||||
getData<T>(ref: ExtensionDataRef<T>): T | undefined;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionTree {
|
||||
getExtension(id: string): ExtensionTreeNode | undefined;
|
||||
getExtensionAttachments(id: string, inputName: string): ExtensionTreeNode[];
|
||||
getRootRoutes(): JSX.Element[];
|
||||
getSidebarItems(): JSX.Element[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function createExtensionTree(options: {
|
||||
config: Config;
|
||||
}): ExtensionTree {
|
||||
const features = getAvailableFeatures(options.config);
|
||||
const tree = createAppTree({
|
||||
features,
|
||||
builtinExtensions,
|
||||
config: options.config,
|
||||
});
|
||||
|
||||
function convertNode(node?: AppNode): ExtensionTreeNode | undefined {
|
||||
return (
|
||||
node && {
|
||||
id: node.spec.id,
|
||||
getData<T>(ref: ExtensionDataRef<T>): T | undefined {
|
||||
return node.instance?.getData(ref);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
getExtension(id: string): ExtensionTreeNode | undefined {
|
||||
return convertNode(tree.nodes.get(id));
|
||||
},
|
||||
getExtensionAttachments(
|
||||
id: string,
|
||||
inputName: string,
|
||||
): ExtensionTreeNode[] {
|
||||
return (
|
||||
tree.nodes
|
||||
.get(id)
|
||||
?.edges.attachments.get(inputName)
|
||||
?.map(convertNode)
|
||||
.filter((node): node is ExtensionTreeNode => Boolean(node)) ?? []
|
||||
);
|
||||
},
|
||||
getRootRoutes(): JSX.Element[] {
|
||||
return this.getExtensionAttachments('app/routes', 'routes').map(node => {
|
||||
const path = node.getData(coreExtensionData.routePath);
|
||||
const element = node.getData(coreExtensionData.reactElement);
|
||||
const routeRef = node.getData(coreExtensionData.routeRef);
|
||||
if (!path || !element) {
|
||||
throw new Error(`Invalid route extension: ${node.id}`);
|
||||
}
|
||||
const Component = () => {
|
||||
return element;
|
||||
};
|
||||
attachComponentData(Component, 'core.mountPoint', routeRef);
|
||||
|
||||
return <Route path={path} element={<Component />} />;
|
||||
});
|
||||
},
|
||||
getSidebarItems(): JSX.Element[] {
|
||||
const RoutedSidebarItem = (props: {
|
||||
title: string;
|
||||
routeRef: RouteRef;
|
||||
icon: IconComponent;
|
||||
}): React.JSX.Element => {
|
||||
const location = useRouteRef(props.routeRef);
|
||||
return (
|
||||
<SidebarItem icon={props.icon} to={location()} text={props.title} />
|
||||
);
|
||||
};
|
||||
|
||||
return this.getExtensionAttachments('app/nav', 'items')
|
||||
.map((node, index) => {
|
||||
const target = node.getData(createNavItemExtension.targetDataRef);
|
||||
if (!target) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<RoutedSidebarItem
|
||||
key={index}
|
||||
title={target.title}
|
||||
icon={target.icon}
|
||||
routeRef={target.routeRef}
|
||||
/>
|
||||
);
|
||||
})
|
||||
.filter((x): x is JSX.Element => !!x);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function deduplicateFeatures(
|
||||
allFeatures: FrontendFeature[],
|
||||
): FrontendFeature[] {
|
||||
|
||||
@@ -17,8 +17,5 @@
|
||||
export {
|
||||
createApp,
|
||||
createSpecializedApp,
|
||||
createExtensionTree,
|
||||
type CreateAppFeatureLoader,
|
||||
type ExtensionTreeNode,
|
||||
type ExtensionTree,
|
||||
} from './createApp';
|
||||
|
||||
Reference in New Issue
Block a user