diff --git a/.changeset/cold-ways-protect.md b/.changeset/cold-ways-protect.md new file mode 100644 index 0000000000..26b693fcc6 --- /dev/null +++ b/.changeset/cold-ways-protect.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-dynamic-feature-service': patch +--- + +Relax type check for a plugin's default export to also accept a BackendFeature defined as a function instead of an object diff --git a/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts b/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts index 9c45cc53f6..1f3c23d1cf 100644 --- a/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts +++ b/packages/backend-dynamic-feature-service/src/manager/plugin-manager.test.ts @@ -246,6 +246,59 @@ describe('backend-dynamic-feature-service', () => { >([]); }, }, + { + name: 'should successfully load a backend plugin wrapped in a BackendFeatureCompatWrapper function', + packageManifest: { + name: 'backend-dynamic-plugin-test', + version: '0.0.0', + backstage: { + role: 'backend-plugin', + }, + main: 'dist/index.cjs.js', + }, + indexFile: { + relativePath: ['dist', 'index.cjs.js'], + content: ` + function backendFeatureCompatWrapper() { + return backendFeatureCompatWrapper; + } + Object.assign(backendFeatureCompatWrapper, { + $$type: "@backstage/BackendFeature", + version: "v1", + }); + const alpha = backendFeatureCompatWrapper; + exports.default = alpha; + `, + }, + expectedLogs(location) { + return { + infos: [ + { + message: `loaded dynamic backend plugin 'backend-dynamic-plugin-test' from '${location}'`, + }, + ], + }; + }, + checkLoadedPlugins(plugins) { + expect(plugins).toMatchObject([ + { + name: 'backend-dynamic-plugin-test', + version: '0.0.0', + role: 'backend-plugin', + platform: 'node', + installer: { + kind: 'new', + }, + }, + ]); + const installer: NewBackendPluginInstaller = ( + plugins[0] as BackendDynamicPlugin + ).installer as NewBackendPluginInstaller; + expect((installer.install() as BackendFeature).$$type).toEqual( + '@backstage/BackendFeature', + ); + }, + }, { name: 'should fail when no index file', packageManifest: { diff --git a/packages/backend-dynamic-feature-service/src/manager/plugin-manager.ts b/packages/backend-dynamic-feature-service/src/manager/plugin-manager.ts index 95b0c6592c..ff0ba76015 100644 --- a/packages/backend-dynamic-feature-service/src/manager/plugin-manager.ts +++ b/packages/backend-dynamic-feature-service/src/manager/plugin-manager.ts @@ -301,7 +301,7 @@ export const dynamicPluginsFeatureDiscoveryServiceFactory = function isBackendFeature(value: unknown): value is BackendFeature { return ( !!value && - typeof value === 'object' && + (typeof value === 'object' || typeof value === 'function') && (value as BackendFeature).$$type === '@backstage/BackendFeature' ); }