chore: make more things swoppable

Signed-off-by: benjdlambert <ben@blam.sh>

Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
benjdlambert
2025-08-06 14:24:17 +02:00
parent d996f05ae5
commit 4b3ba2b048
17 changed files with 228 additions and 172 deletions
+93 -57
View File
@@ -8,7 +8,6 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api';
import { AnyRouteRefParams } from '@backstage/frontend-plugin-api';
import { ApiFactory } from '@backstage/frontend-plugin-api';
import { AppTheme } from '@backstage/frontend-plugin-api';
import { ComponentRef } from '@backstage/frontend-plugin-api';
import { ComponentType } from 'react';
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api';
@@ -23,6 +22,7 @@ import { NavContentComponent } from '@backstage/frontend-plugin-api';
import { ReactNode } from 'react';
import { RouteRef } from '@backstage/frontend-plugin-api';
import { SignInPageProps } from '@backstage/core-plugin-api';
import { SwappableComponentRef } from '@backstage/frontend-plugin-api';
import { TranslationMessages } from '@backstage/frontend-plugin-api';
import { TranslationResource } from '@backstage/frontend-plugin-api';
@@ -315,38 +315,6 @@ const appPlugin: FrontendPlugin<
params: ApiFactory<TApi, TImpl, TDeps>,
) => ExtensionBlueprintParams<AnyApiFactory>;
}>;
'api:app/components': ExtensionDefinition<{
config: {};
configInput: {};
output: ExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>;
inputs: {
components: ExtensionInput<
ConfigurableExtensionDataRef<
{
ref: ComponentRef;
loader:
| (() => (props: {}) => JSX.Element | null)
| (() => Promise<(props: {}) => JSX.Element | null>);
},
'core.component.component',
{}
>,
{
singleton: false;
optional: false;
}
>;
};
kind: 'api';
name: 'components';
params: <
TApi,
TImpl extends TApi,
TDeps extends { [name in string]: unknown },
>(
params: ApiFactory<TApi, TImpl, TDeps>,
) => ExtensionBlueprintParams<AnyApiFactory>;
}>;
'api:app/dialog': ExtensionDefinition<{
kind: 'api';
name: 'dialog';
@@ -616,6 +584,38 @@ const appPlugin: FrontendPlugin<
params: ApiFactory<TApi, TImpl, TDeps>,
) => ExtensionBlueprintParams<AnyApiFactory>;
}>;
'api:app/swappable-components': ExtensionDefinition<{
config: {};
configInput: {};
output: ExtensionDataRef<AnyApiFactory, 'core.api.factory', {}>;
inputs: {
components: ExtensionInput<
ConfigurableExtensionDataRef<
{
ref: SwappableComponentRef;
loader:
| (() => (props: {}) => JSX.Element | null)
| (() => Promise<(props: {}) => JSX.Element | null>);
},
'core.component.component',
{}
>,
{
singleton: false;
optional: false;
}
>;
};
kind: 'api';
name: 'swappable-components';
params: <
TApi,
TImpl extends TApi,
TDeps extends { [name in string]: unknown },
>(
params: ApiFactory<TApi, TImpl, TDeps>,
) => ExtensionBlueprintParams<AnyApiFactory>;
}>;
'api:app/translations': ExtensionDefinition<{
config: {};
configInput: {};
@@ -735,7 +735,7 @@ const appPlugin: FrontendPlugin<
configInput: {};
output: ExtensionDataRef<
{
ref: ComponentRef;
ref: SwappableComponentRef;
loader:
| (() => (props: {}) => JSX.Element | null)
| (() => Promise<(props: {}) => JSX.Element | null>);
@@ -744,13 +744,19 @@ const appPlugin: FrontendPlugin<
{}
>;
inputs: {};
params: <Ref extends ComponentRef<any>>(params: {
component: Ref extends ComponentRef<any, infer IExternalComponentProps>
params: <Ref extends SwappableComponentRef<any>>(params: {
component: Ref extends SwappableComponentRef<
any,
infer IExternalComponentProps
>
? {
ref: Ref;
} & ((props: IExternalComponentProps) => JSX.Element)
} & ((props: IExternalComponentProps) => JSX.Element | null)
: never;
loader: Ref extends ComponentRef<infer IInnerComponentProps, any>
loader: Ref extends SwappableComponentRef<
infer IInnerComponentProps,
any
>
?
| (() => (props: IInnerComponentProps) => JSX.Element | null)
| (() => Promise<
@@ -758,12 +764,18 @@ const appPlugin: FrontendPlugin<
>)
: never;
}) => ExtensionBlueprintParams<{
component: Ref extends ComponentRef<any, infer IExternalComponentProps>
component: Ref extends SwappableComponentRef<
any,
infer IExternalComponentProps
>
? {
ref: Ref;
} & ((props: IExternalComponentProps) => JSX.Element)
} & ((props: IExternalComponentProps) => JSX.Element | null)
: never;
loader: Ref extends ComponentRef<infer IInnerComponentProps, any>
loader: Ref extends SwappableComponentRef<
infer IInnerComponentProps,
any
>
?
| (() => (props: IInnerComponentProps) => JSX.Element | null)
| (() => Promise<
@@ -779,7 +791,7 @@ const appPlugin: FrontendPlugin<
configInput: {};
output: ExtensionDataRef<
{
ref: ComponentRef;
ref: SwappableComponentRef;
loader:
| (() => (props: {}) => JSX.Element | null)
| (() => Promise<(props: {}) => JSX.Element | null>);
@@ -788,13 +800,19 @@ const appPlugin: FrontendPlugin<
{}
>;
inputs: {};
params: <Ref extends ComponentRef<any>>(params: {
component: Ref extends ComponentRef<any, infer IExternalComponentProps>
params: <Ref extends SwappableComponentRef<any>>(params: {
component: Ref extends SwappableComponentRef<
any,
infer IExternalComponentProps
>
? {
ref: Ref;
} & ((props: IExternalComponentProps) => JSX.Element)
} & ((props: IExternalComponentProps) => JSX.Element | null)
: never;
loader: Ref extends ComponentRef<infer IInnerComponentProps, any>
loader: Ref extends SwappableComponentRef<
infer IInnerComponentProps,
any
>
?
| (() => (props: IInnerComponentProps) => JSX.Element | null)
| (() => Promise<
@@ -802,12 +820,18 @@ const appPlugin: FrontendPlugin<
>)
: never;
}) => ExtensionBlueprintParams<{
component: Ref extends ComponentRef<any, infer IExternalComponentProps>
component: Ref extends SwappableComponentRef<
any,
infer IExternalComponentProps
>
? {
ref: Ref;
} & ((props: IExternalComponentProps) => JSX.Element)
} & ((props: IExternalComponentProps) => JSX.Element | null)
: never;
loader: Ref extends ComponentRef<infer IInnerComponentProps, any>
loader: Ref extends SwappableComponentRef<
infer IInnerComponentProps,
any
>
?
| (() => (props: IInnerComponentProps) => JSX.Element | null)
| (() => Promise<
@@ -823,7 +847,7 @@ const appPlugin: FrontendPlugin<
configInput: {};
output: ExtensionDataRef<
{
ref: ComponentRef;
ref: SwappableComponentRef;
loader:
| (() => (props: {}) => JSX.Element | null)
| (() => Promise<(props: {}) => JSX.Element | null>);
@@ -832,13 +856,19 @@ const appPlugin: FrontendPlugin<
{}
>;
inputs: {};
params: <Ref extends ComponentRef<any>>(params: {
component: Ref extends ComponentRef<any, infer IExternalComponentProps>
params: <Ref extends SwappableComponentRef<any>>(params: {
component: Ref extends SwappableComponentRef<
any,
infer IExternalComponentProps
>
? {
ref: Ref;
} & ((props: IExternalComponentProps) => JSX.Element)
} & ((props: IExternalComponentProps) => JSX.Element | null)
: never;
loader: Ref extends ComponentRef<infer IInnerComponentProps, any>
loader: Ref extends SwappableComponentRef<
infer IInnerComponentProps,
any
>
?
| (() => (props: IInnerComponentProps) => JSX.Element | null)
| (() => Promise<
@@ -846,12 +876,18 @@ const appPlugin: FrontendPlugin<
>)
: never;
}) => ExtensionBlueprintParams<{
component: Ref extends ComponentRef<any, infer IExternalComponentProps>
component: Ref extends SwappableComponentRef<
any,
infer IExternalComponentProps
>
? {
ref: Ref;
} & ((props: IExternalComponentProps) => JSX.Element)
} & ((props: IExternalComponentProps) => JSX.Element | null)
: never;
loader: Ref extends ComponentRef<infer IInnerComponentProps, any>
loader: Ref extends SwappableComponentRef<
infer IInnerComponentProps,
any
>
?
| (() => (props: IInnerComponentProps) => JSX.Element | null)
| (() => Promise<
@@ -18,16 +18,16 @@ import {
SwappableComponentBlueprint,
createExtensionInput,
ApiBlueprint,
componentsApiRef,
swappableComponentsApiRef,
} from '@backstage/frontend-plugin-api';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { DefaultComponentsApi } from '../../../../packages/frontend-app-api/src/apis/implementations/ComponentsApi';
import { DefaultSwappableComponentsApi } from '../../../../packages/frontend-app-api/src/apis/implementations/SwappableComponentsApi';
/**
* Contains the shareable components installed into the app.
*/
export const ComponentsApi = ApiBlueprint.makeWithOverrides({
name: 'components',
export const SwappableComponentsApi = ApiBlueprint.makeWithOverrides({
name: 'swappable-components',
inputs: {
components: createExtensionInput(
[SwappableComponentBlueprint.dataRefs.component],
@@ -37,10 +37,10 @@ export const ComponentsApi = ApiBlueprint.makeWithOverrides({
factory: (originalFactory, { inputs }) => {
return originalFactory(defineParams =>
defineParams({
api: componentsApiRef,
api: swappableComponentsApiRef,
deps: {},
factory: () =>
DefaultComponentsApi.fromComponents(
DefaultSwappableComponentsApi.fromComponents(
inputs.components.map(i =>
i.get(SwappableComponentBlueprint.dataRefs.component),
),
+1 -1
View File
@@ -20,7 +20,7 @@ export { AppNav } from './AppNav';
export { AppRoot } from './AppRoot';
export { AppRoutes } from './AppRoutes';
export { AppThemeApi, DarkTheme, LightTheme } from './AppThemeApi';
export { ComponentsApi } from './ComponentsApi';
export { SwappableComponentsApi } from './SwappableComponentsApi';
export { IconsApi } from './IconsApi';
export { FeatureFlagsApi } from './FeatureFlagsApi';
export { TranslationsApi } from './TranslationsApi';
+2 -2
View File
@@ -25,7 +25,7 @@ import {
AppThemeApi,
DarkTheme,
LightTheme,
ComponentsApi,
SwappableComponentsApi,
IconsApi,
FeatureFlagsApi,
TranslationsApi,
@@ -54,7 +54,7 @@ export const appPlugin = createFrontendPlugin({
AppThemeApi,
DarkTheme,
LightTheme,
ComponentsApi,
SwappableComponentsApi,
IconsApi,
FeatureFlagsApi,
TranslationsApi,