From 4a3885943a9290851ad498b60783b34877872dc0 Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Thu, 31 Jul 2025 16:19:22 +0200 Subject: [PATCH 1/5] chore: changing the name from Component to component Signed-off-by: benjdlambert --- .../src/blueprints/AppRootWrapperBlueprint.test.tsx | 6 +++--- .../src/blueprints/AppRootWrapperBlueprint.tsx | 9 ++------- .../src/blueprints/RouterBlueprint.test.tsx | 6 +++--- .../src/blueprints/RouterBlueprint.tsx | 4 ++-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx index d46975abd9..b4ad8ed2d2 100644 --- a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx @@ -27,7 +27,7 @@ describe('AppRootWrapperBlueprint', () => { it('should return an extension with sensible defaults', () => { const extension = AppRootWrapperBlueprint.make({ params: { - Component: () =>
Hello
, + component: () =>
Hello
, }, }); @@ -59,7 +59,7 @@ describe('AppRootWrapperBlueprint', () => { const extension = AppRootWrapperBlueprint.make({ name: 'test', params: { - Component: () =>
Hello
, + component: () =>
Hello
, }, }); @@ -80,7 +80,7 @@ describe('AppRootWrapperBlueprint', () => { }, *factory(originalFactory, { inputs, config }) { yield* originalFactory({ - Component: ({ children }) => ( + component: ({ children }) => (
{children} {inputs.children.flatMap(c => diff --git a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx index 481be1bc0b..ca5ea2d5fa 100644 --- a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx @@ -35,12 +35,7 @@ export const AppRootWrapperBlueprint = createExtensionBlueprint({ dataRefs: { component: componentDataRef, }, - *factory(params: { Component: ComponentType> }) { - // todo(blam): not sure that this wrapping is even necessary anymore. - const Component = (props: PropsWithChildren<{}>) => { - return {props.children}; - }; - - yield componentDataRef(Component); + *factory(params: { component: ComponentType> }) { + yield componentDataRef(params.component); }, }); diff --git a/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.test.tsx index 00015d0c3d..f2e5199124 100644 --- a/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.test.tsx @@ -27,7 +27,7 @@ describe('RouterBlueprint', () => { it('should return an extension when calling make with sensible defaults', () => { const extension = RouterBlueprint.make({ params: { - Component: props =>
{props.children}
, + component: props =>
{props.children}
, }, }); @@ -58,7 +58,7 @@ describe('RouterBlueprint', () => { it('should work with simple options', async () => { const extension = RouterBlueprint.make({ params: { - Component: ({ children }) => ( + component: ({ children }) => (
{children}
@@ -94,7 +94,7 @@ describe('RouterBlueprint', () => { }, *factory(originalFactory, { inputs, config }) { yield* originalFactory({ - Component: ({ children }) => ( + component: ({ children }) => (
> }) { - yield componentDataRef(Component); + *factory({ component }: { component: ComponentType> }) { + yield componentDataRef(component); }, }); From a060e618b1564e4ce04d703a97e94b26a76dba3e Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Thu, 31 Jul 2025 16:23:14 +0200 Subject: [PATCH 2/5] chore: remove `ComponentType` types Signed-off-by: benjdlambert --- .../src/blueprints/AppRootWrapperBlueprint.tsx | 8 +++++--- .../src/blueprints/RouterBlueprint.tsx | 10 +++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx index ca5ea2d5fa..1002f9a383 100644 --- a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx @@ -14,11 +14,11 @@ * limitations under the License. */ -import { ComponentType, PropsWithChildren } from 'react'; +import { ReactNode } from 'react'; import { createExtensionBlueprint, createExtensionDataRef } from '../wiring'; const componentDataRef = createExtensionDataRef< - ComponentType> + (props: { children: ReactNode }) => JSX.Element | null >().with({ id: 'app.root.wrapper' }); /** @@ -35,7 +35,9 @@ export const AppRootWrapperBlueprint = createExtensionBlueprint({ dataRefs: { component: componentDataRef, }, - *factory(params: { component: ComponentType> }) { + *factory(params: { + component: (props: { children: ReactNode }) => JSX.Element | null; + }) { yield componentDataRef(params.component); }, }); diff --git a/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx index 308d560f00..97870b8589 100644 --- a/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx @@ -14,11 +14,11 @@ * limitations under the License. */ -import { ComponentType, PropsWithChildren } from 'react'; +import { ReactNode } from 'react'; import { createExtensionBlueprint, createExtensionDataRef } from '../wiring'; const componentDataRef = createExtensionDataRef< - ComponentType> + (props: { children: ReactNode }) => JSX.Element | null >().with({ id: 'app.router.wrapper' }); /** @public */ @@ -29,7 +29,11 @@ export const RouterBlueprint = createExtensionBlueprint({ dataRefs: { component: componentDataRef, }, - *factory({ component }: { component: ComponentType> }) { + *factory({ + component, + }: { + component: (props: { children: ReactNode }) => JSX.Element | null; + }) { yield componentDataRef(component); }, }); From b465fbb09b661819de5f61910bc98932d8f6b1de Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Thu, 31 Jul 2025 16:38:53 +0200 Subject: [PATCH 3/5] chore: fixing types Signed-off-by: benjdlambert --- .../src/convertLegacyAppOptions.tsx | 2 +- packages/frontend-plugin-api/report.api.md | 21 ++++++------------- .../src/app/renderInTestApp.tsx | 2 +- plugins/app/report.api.md | 8 ++----- plugins/app/src/extensions/AppRoot.tsx | 2 +- 5 files changed, 11 insertions(+), 24 deletions(-) diff --git a/packages/core-compat-api/src/convertLegacyAppOptions.tsx b/packages/core-compat-api/src/convertLegacyAppOptions.tsx index c98875464c..9da935957a 100644 --- a/packages/core-compat-api/src/convertLegacyAppOptions.tsx +++ b/packages/core-compat-api/src/convertLegacyAppOptions.tsx @@ -139,7 +139,7 @@ export function convertLegacyAppOptions( if (Router) { extensions.push( RouterBlueprint.make({ - params: { Component: componentCompatWrapper(Router) }, + params: { component: componentCompatWrapper(Router) }, }), ); } diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 8ae1960221..b91295630b 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -71,7 +71,6 @@ import { OpenIdConnectApi } from '@backstage/core-plugin-api'; import { PendingOAuthRequest } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; import { ProfileInfoApi } from '@backstage/core-plugin-api'; -import { PropsWithChildren } from 'react'; import { ReactNode } from 'react'; import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api'; import { SessionApi } from '@backstage/core-plugin-api'; @@ -268,12 +267,10 @@ export const AppRootWrapperBlueprint: ExtensionBlueprint<{ kind: 'app-root-wrapper'; name: undefined; params: { - Component: ComponentType>; + component: (props: { children: ReactNode }) => JSX.Element | null; }; output: ConfigurableExtensionDataRef< - ComponentType<{ - children?: ReactNode | undefined; - }>, + (props: { children: ReactNode }) => JSX.Element | null, 'app.root.wrapper', {} >; @@ -282,9 +279,7 @@ export const AppRootWrapperBlueprint: ExtensionBlueprint<{ configInput: {}; dataRefs: { component: ConfigurableExtensionDataRef< - ComponentType<{ - children?: ReactNode | undefined; - }>, + (props: { children: ReactNode }) => JSX.Element | null, 'app.root.wrapper', {} >; @@ -1724,12 +1719,10 @@ export const RouterBlueprint: ExtensionBlueprint<{ kind: 'app-router-component'; name: undefined; params: { - Component: ComponentType>; + component: (props: { children: ReactNode }) => JSX.Element | null; }; output: ConfigurableExtensionDataRef< - ComponentType<{ - children?: ReactNode | undefined; - }>, + (props: { children: ReactNode }) => JSX.Element | null, 'app.router.wrapper', {} >; @@ -1738,9 +1731,7 @@ export const RouterBlueprint: ExtensionBlueprint<{ configInput: {}; dataRefs: { component: ConfigurableExtensionDataRef< - ComponentType<{ - children?: ReactNode | undefined; - }>, + (props: { children: ReactNode }) => JSX.Element | null, 'app.router.wrapper', {} >; diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index d4010a92ad..e308cf9741 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -160,7 +160,7 @@ export function renderInTestApp( }), RouterBlueprint.make({ params: { - Component: ({ children }) => ( + component: ({ children }) => ( {children} diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index 15001d2961..4eb1ff76fc 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -130,9 +130,7 @@ const appPlugin: FrontendPlugin< inputs: { router: ExtensionInput< ConfigurableExtensionDataRef< - ComponentType<{ - children?: ReactNode | undefined; - }>, + (props: { children: ReactNode }) => JSX.Element | null, 'app.router.wrapper', {} >, @@ -168,9 +166,7 @@ const appPlugin: FrontendPlugin< >; wrappers: ExtensionInput< ConfigurableExtensionDataRef< - ComponentType<{ - children?: ReactNode | undefined; - }>, + (props: { children: ReactNode }) => JSX.Element | null, 'app.root.wrapper', {} >, diff --git a/plugins/app/src/extensions/AppRoot.tsx b/plugins/app/src/extensions/AppRoot.tsx index 17e8aa3b1f..9ce2b055dd 100644 --- a/plugins/app/src/extensions/AppRoot.tsx +++ b/plugins/app/src/extensions/AppRoot.tsx @@ -182,7 +182,7 @@ type RouteResolverProxy = { export interface AppRouterProps { children?: ReactNode; SignInPageComponent?: ComponentType; - RouterComponent?: ComponentType>; + RouterComponent?: (props: { children: ReactNode }) => JSX.Element | null; extraElements?: Array; } From 5d31d66e6be86daf9ce51c17e38519ed13b8fd86 Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Thu, 31 Jul 2025 16:44:17 +0200 Subject: [PATCH 4/5] chore: added changesets Signed-off-by: benjdlambert --- .changeset/green-lies-invite copy.md | 39 ++++++++++++++++++++++++++++ .changeset/green-lies-invite.md | 7 +++++ 2 files changed, 46 insertions(+) create mode 100644 .changeset/green-lies-invite copy.md create mode 100644 .changeset/green-lies-invite.md diff --git a/.changeset/green-lies-invite copy.md b/.changeset/green-lies-invite copy.md new file mode 100644 index 0000000000..469ed2fbac --- /dev/null +++ b/.changeset/green-lies-invite copy.md @@ -0,0 +1,39 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +**BREAKING**: In an attempt to align some of the API's around providing components to `Blueprints`, we've renamed the parameters for both the `RouterBlueprint` and `AppRootWrapperBlueprint` from `Component` to `component`. + +```tsx +// old +RouterBlueprint.make({ + params: { + Component: ({ children }) =>
{children}
, + }, +}); + +// new +RouterBlueprint.make({ + params: { + component: ({ children }) =>
{children}
, + }, +}); +``` + +```tsx +// old +AppRootWrapperBlueprint.make({ + params: { + Component: ({ children }) =>
{children}
, + }, +}); + +// new +AppRootWrapperBlueprint.make({ + params: { + component: ({ children }) =>
{children}
, + }, +}); +``` + +As part of this change, the type for `component` has also changed from `ComponentType>` to `(props: { children: ReactNode }) => JSX.Element | null` which is not breaking, just a little more reflective of the actual expected component. diff --git a/.changeset/green-lies-invite.md b/.changeset/green-lies-invite.md new file mode 100644 index 0000000000..92ccc2324d --- /dev/null +++ b/.changeset/green-lies-invite.md @@ -0,0 +1,7 @@ +--- +'@backstage/frontend-test-utils': patch +'@backstage/core-compat-api': patch +'@backstage/plugin-app': patch +--- + +Updated the usage of the `RouterBlueprint` and `AppRootWrapperBlueprint` to use the lowercase `component` parameter From 727c83bddc0586fad1a2e2f422fc9d339c995cd7 Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Mon, 4 Aug 2025 11:04:45 +0200 Subject: [PATCH 5/5] chore: added some helper error message for removal of the `Component` param Signed-off-by: benjdlambert --- packages/frontend-plugin-api/report.api.md | 2 ++ .../src/blueprints/AppRootWrapperBlueprint.tsx | 2 ++ .../src/blueprints/RouterBlueprint.tsx | 8 ++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index b91295630b..bda12a8d89 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -267,6 +267,7 @@ export const AppRootWrapperBlueprint: ExtensionBlueprint<{ kind: 'app-root-wrapper'; name: undefined; params: { + Component?: [error: 'Use the `component` parameter instead']; component: (props: { children: ReactNode }) => JSX.Element | null; }; output: ConfigurableExtensionDataRef< @@ -1719,6 +1720,7 @@ export const RouterBlueprint: ExtensionBlueprint<{ kind: 'app-router-component'; name: undefined; params: { + Component?: [error: 'Use the `component` parameter instead']; component: (props: { children: ReactNode }) => JSX.Element | null; }; output: ConfigurableExtensionDataRef< diff --git a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx index 1002f9a383..493fba05f6 100644 --- a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx @@ -36,6 +36,8 @@ export const AppRootWrapperBlueprint = createExtensionBlueprint({ component: componentDataRef, }, *factory(params: { + /** @deprecated use the `component` parameter instead */ + Component?: [error: 'Use the `component` parameter instead']; component: (props: { children: ReactNode }) => JSX.Element | null; }) { yield componentDataRef(params.component); diff --git a/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx index 97870b8589..c4b7c16bd6 100644 --- a/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/RouterBlueprint.tsx @@ -29,11 +29,11 @@ export const RouterBlueprint = createExtensionBlueprint({ dataRefs: { component: componentDataRef, }, - *factory({ - component, - }: { + *factory(params: { + /** @deprecated use the `component` parameter instead */ + Component?: [error: 'Use the `component` parameter instead']; component: (props: { children: ReactNode }) => JSX.Element | null; }) { - yield componentDataRef(component); + yield componentDataRef(params.component); }, });