diff --git a/.changeset/cold-lemons-design.md b/.changeset/cold-lemons-design.md new file mode 100644 index 0000000000..9bdadac9c7 --- /dev/null +++ b/.changeset/cold-lemons-design.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-app': patch +--- + +Log a warning when `SwappableComponent` extensions are installed outside of using the `app` plugin diff --git a/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx b/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx index 823d48e21c..07ef891926 100644 --- a/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx +++ b/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx @@ -17,6 +17,7 @@ import { ApiBlueprint, createExtensionInput, + createFrontendModule, createSwappableComponent, SwappableComponentBlueprint, swappableComponentsApiRef, @@ -202,7 +203,13 @@ describe('DefaultSwappableComponentsApi', () => { }); renderInTestApp(, { - extensions: [api, override], + extensions: [api], + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [override], + }), + ], }); await expect( @@ -225,7 +232,13 @@ describe('DefaultSwappableComponentsApi', () => { }); renderInTestApp(, { - extensions: [api, override], + extensions: [api], + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [override], + }), + ], }); await expect( @@ -252,7 +265,13 @@ describe('DefaultSwappableComponentsApi', () => { }); renderInTestApp(, { - extensions: [api, override], + extensions: [api], + features: [ + createFrontendModule({ + pluginId: 'app', + extensions: [override], + }), + ], }); await expect( diff --git a/plugins/app/src/extensions/SwappableComponentsApi.ts b/plugins/app/src/extensions/SwappableComponentsApi.ts index ea57a6f487..f261d999c0 100644 --- a/plugins/app/src/extensions/SwappableComponentsApi.ts +++ b/plugins/app/src/extensions/SwappableComponentsApi.ts @@ -37,12 +37,30 @@ export const SwappableComponentsApi = ApiBlueprint.makeWithOverrides({ defineParams({ api: swappableComponentsApiRef, deps: {}, - factory: () => - DefaultSwappableComponentsApi.fromComponents( - inputs.components.map(i => + factory: () => { + const nonAppExtensions = inputs.components.filter( + i => i.node.spec.plugin?.id !== 'app', + ); + + if (nonAppExtensions.length > 0) { + // eslint-disable-next-line no-console + console.warn( + `SwappableComponents should only be installed as an extension in the app plugin. You can either use appPlugin.override(), or provide a module for the app-plugin with the extension there instead. Invalid extensions: ${nonAppExtensions + .map(i => i.node.spec.id) + .join(', ')}`, + ); + } + + const appExtensions = inputs.components.filter( + i => i.node.spec.plugin?.id === 'app', + ); + + return DefaultSwappableComponentsApi.fromComponents( + appExtensions.map(i => i.get(SwappableComponentBlueprint.dataRefs.component), ), - ), + ); + }, }), ); },