frontend-app-api: remove experimental createExtensionTree API

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-01-25 13:41:38 +01:00
committed by blam
parent 26ad51238c
commit bdf4a8e176
6 changed files with 8 additions and 165 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': minor
---
**BREAKING**: Removed the experimental `createExtensionTree` API.
+2 -23
View File
@@ -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 />
-25
View File
@@ -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';