diff --git a/packages/frontend-app-api/src/extensions/Core.tsx b/packages/frontend-app-api/src/extensions/Core.tsx index 441cb5bcf0..4347eb1b45 100644 --- a/packages/frontend-app-api/src/extensions/Core.tsx +++ b/packages/frontend-app-api/src/extensions/Core.tsx @@ -18,7 +18,9 @@ import { coreExtensionData, createExtension, createExtensionInput, + ComponentsProvider, } from '@backstage/frontend-plugin-api'; +import React from 'react'; export const Core = createExtension({ id: 'core', @@ -44,8 +46,20 @@ export const Core = createExtension({ root: coreExtensionData.reactElement, }, factory({ inputs }) { + const components = inputs.components.reduce( + (rest, { component }) => ({ + ...rest, + [component.ref.id]: component.impl, + }), + {}, + ); + return { - root: inputs.root.element, + root: ( + + {inputs.root.element} + + ), }; }, }); diff --git a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx index e2798c091d..b2918cfcc9 100644 --- a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx +++ b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx @@ -19,10 +19,10 @@ import { createExtension, coreExtensionData, createExtensionInput, + coreNotFoundErrorPageComponentRef, + useComponent, } from '@backstage/frontend-plugin-api'; import { useRoutes } from 'react-router-dom'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { useApp } from '../../../core-plugin-api/src/app/useApp'; export const CoreRoutes = createExtension({ id: 'core.routes', @@ -39,8 +39,8 @@ export const CoreRoutes = createExtension({ }, factory({ inputs }) { const Routes = () => { - const app = useApp(); - const { NotFoundErrorPage } = app.getComponents(); + const NotFoundErrorPage = useComponent(coreNotFoundErrorPageComponentRef); + const element = useRoutes([ ...inputs.routes.map(route => ({ path: `${route.path}/*`, diff --git a/packages/frontend-plugin-api/src/components/ComponentsContext.tsx b/packages/frontend-plugin-api/src/components/ComponentsContext.tsx new file mode 100644 index 0000000000..7b1058f83c --- /dev/null +++ b/packages/frontend-plugin-api/src/components/ComponentsContext.tsx @@ -0,0 +1,58 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentRef } from '@backstage/frontend-plugin-api'; +import { + createVersionedContext, + createVersionedValueMap, + useVersionedContext, +} from '@backstage/version-bridge'; +import React from 'react'; +import { ComponentType, PropsWithChildren } from 'react'; + +/** @public */ +export type ComponentsContextValue = Record>; + +const ComponentsContext = createVersionedContext<{ 1: ComponentsContextValue }>( + 'components-context', +); + +/** @public */ +export function ComponentsProvider( + props: PropsWithChildren<{ value: ComponentsContextValue }>, +) { + const { value, children } = props; + return ( + + {children} + + ); +} + +/** @public */ +export function useComponent< + P extends {}, + T extends ComponentRef>, +>(ref: T): T['T'] { + const components = useVersionedContext<{ 1: ComponentsContextValue }>( + 'components-context', + ); + const component = components?.atVersion(1)?.[ref.id]; + if (!component) { + throw new Error(`No implementation available for ${ref.id}`); + } + return component; +} diff --git a/packages/frontend-plugin-api/src/components/index.ts b/packages/frontend-plugin-api/src/components/index.ts index 4bee5c5f7b..575e5efbe0 100644 --- a/packages/frontend-plugin-api/src/components/index.ts +++ b/packages/frontend-plugin-api/src/components/index.ts @@ -14,6 +14,12 @@ * limitations under the License. */ +export { + ComponentsProvider, + useComponent, + type ComponentsContextValue, +} from './ComponentsContext'; + export { coreProgressComponentRef, coreBootErrorPageComponentRef,