diff --git a/.changeset/breezy-cobras-sin.md b/.changeset/breezy-cobras-sin.md new file mode 100644 index 0000000000..93b296c455 --- /dev/null +++ b/.changeset/breezy-cobras-sin.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': minor +--- + +**BREAKING**: Removed the experimental `createExtensionTree` API. diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index d2dde95f68..90190b50be 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -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 = ( } /> @@ -258,10 +241,6 @@ const routes = ( path="/tech-radar" element={} /> - { - /* HIGHLY EXPERIMENTAL. DO NOT USE THIS IN YOUR APP */ extensionTree?.getRootRoutes() ?? - null - } } /> } /> } /> @@ -302,7 +281,7 @@ export default app.createRoot( - {routes} + {routes} , ); diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 066ba4d05b..ec5f9dabe2 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -84,7 +84,6 @@ const SidebarLogo = () => { export const Root = ({ children, - extensionTree, }: PropsWithChildren<{ extensionTree?: ExtensionTree }>) => ( @@ -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 - } diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index d0aadb7e8c..3236b05a01 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -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(ref: ExtensionDataRef): T | undefined; - // (undocumented) - id: string; -} ``` diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 6966ef87c3..635e36aace 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -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(ref: ExtensionDataRef): 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(ref: ExtensionDataRef): 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 } />; - }); - }, - getSidebarItems(): JSX.Element[] { - const RoutedSidebarItem = (props: { - title: string; - routeRef: RouteRef; - icon: IconComponent; - }): React.JSX.Element => { - const location = useRouteRef(props.routeRef); - return ( - - ); - }; - - return this.getExtensionAttachments('app/nav', 'items') - .map((node, index) => { - const target = node.getData(createNavItemExtension.targetDataRef); - if (!target) { - return null; - } - return ( - - ); - }) - .filter((x): x is JSX.Element => !!x); - }, - }; -} - function deduplicateFeatures( allFeatures: FrontendFeature[], ): FrontendFeature[] { diff --git a/packages/frontend-app-api/src/wiring/index.ts b/packages/frontend-app-api/src/wiring/index.ts index 00c6458bd5..d1498514c8 100644 --- a/packages/frontend-app-api/src/wiring/index.ts +++ b/packages/frontend-app-api/src/wiring/index.ts @@ -17,8 +17,5 @@ export { createApp, createSpecializedApp, - createExtensionTree, type CreateAppFeatureLoader, - type ExtensionTreeNode, - type ExtensionTree, } from './createApp';