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,