diff --git a/.changeset/red-ghosts-train.md b/.changeset/red-ghosts-train.md new file mode 100644 index 0000000000..daa6692820 --- /dev/null +++ b/.changeset/red-ghosts-train.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: Removed the ability to define options for plugins and modules. Existing options should be migrated to instead use either static configuration or extension points. diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 9fa2149e43..0789168926 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -119,14 +119,14 @@ export namespace coreServices { } // @public -export function createBackendModule( - config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), -): (...params: TOptions) => BackendFeature; +export function createBackendModule( + config: BackendModuleConfig, +): () => BackendFeature; // @public -export function createBackendPlugin( - config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), -): (...params: TOptions) => BackendFeature; +export function createBackendPlugin( + config: BackendPluginConfig, +): () => BackendFeature; // @public export function createExtensionPoint( diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index 17b0eed55f..1fd05a1605 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -33,22 +33,19 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { - const plugin = createBackendPlugin((_options: { a: string }) => ({ + const plugin = createBackendPlugin({ pluginId: 'x', register(r) { r.registerInit({ deps: {}, async init() {} }); }, - })); + }); expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' })).toEqual({ + expect(plugin()).toEqual({ $$type: '@backstage/BackendFeature', version: 'v1', getRegistrations: expect.any(Function), }); - expect( - (plugin({ a: 'a' }) as InternalBackendFeature).getRegistrations(), - ).toEqual([ + expect((plugin() as InternalBackendFeature).getRegistrations()).toEqual([ { type: 'plugin', pluginId: 'x', @@ -60,91 +57,27 @@ describe('createBackendPlugin', () => { }, ]); // @ts-expect-error - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins with optional options', () => { - const plugin = createBackendPlugin((_options?: { a: string }) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins without options', () => { - const plugin = createBackendPlugin({ - pluginId: 'x', - register() {}, - }); - expect(plugin).toBeDefined(); - // @ts-expect-error - expect(plugin({ a: 'a' })).toBeDefined(); - // @ts-expect-error - expect(plugin({})).toBeDefined(); - }); - - it('should create a BackendPlugin with options as interface', () => { - interface TestOptions { - a: string; - } - const plugin = createBackendPlugin((_options: TestOptions) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' })).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - // @ts-expect-error - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins with optional options as interface', () => { - interface TestOptions { - a: string; - } - const plugin = createBackendPlugin((_options?: TestOptions) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); }); }); describe('createBackendModule', () => { it('should create a BackendModule', () => { - const mod = createBackendModule((_options: { a: string }) => ({ + const mod = createBackendModule({ pluginId: 'x', moduleId: 'y', register(r) { r.registerInit({ deps: {}, async init() {} }); }, - })); + }); expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' })).toEqual({ + expect(mod()).toBeDefined(); + expect(mod()).toEqual({ $$type: '@backstage/BackendFeature', version: 'v1', getRegistrations: expect.any(Function), }); - expect( - (mod({ a: 'a' }) as InternalBackendFeature).getRegistrations(), - ).toEqual([ + expect((mod() as InternalBackendFeature).getRegistrations()).toEqual([ { type: 'module', pluginId: 'x', @@ -157,72 +90,6 @@ describe('createBackendModule', () => { }, ]); // @ts-expect-error - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules with optional options', () => { - const mod = createBackendModule((_options?: { a: string }) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules without options', () => { - const mod = createBackendModule({ - pluginId: 'x', - moduleId: 'y', - register() {}, - }); - expect(mod).toBeDefined(); - // @ts-expect-error - expect(mod({ a: 'a' })).toBeDefined(); - // @ts-expect-error - expect(mod({})).toBeDefined(); - }); - - it('should create a BackendModule as interface', () => { - interface TestOptions { - a: string; - } - const mod = createBackendModule((_options: TestOptions) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' })).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - // @ts-expect-error - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules with optional options as interface', () => { - interface TestOptions { - a: string; - } - const mod = createBackendModule((_options?: TestOptions) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); }); }); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index c2ff1f84b9..af40256411 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -85,14 +85,10 @@ export interface BackendPluginConfig { * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins} * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ -export function createBackendPlugin( - config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), -): (...params: TOptions) => BackendFeature { - const configCallback = typeof config === 'function' ? config : () => config; - - const factory: BackendFeatureFactory = (...options) => { - const c = configCallback(...options); - +export function createBackendPlugin( + config: BackendPluginConfig, +): () => BackendFeature { + const factory: BackendFeatureFactory = () => { let registrations: InternalBackendPluginRegistration[]; return { @@ -107,7 +103,7 @@ export function createBackendPlugin( let init: InternalBackendPluginRegistration['init'] | undefined = undefined; - c.register({ + config.register({ registerExtensionPoint(ext, impl) { if (init) { throw new Error( @@ -129,14 +125,14 @@ export function createBackendPlugin( if (!init) { throw new Error( - `registerInit was not called by register in ${c.pluginId}`, + `registerInit was not called by register in ${config.pluginId}`, ); } registrations = [ { type: 'plugin', - pluginId: c.pluginId, + pluginId: config.pluginId, extensionPoints, init, }, @@ -179,13 +175,10 @@ export interface BackendModuleConfig { * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules} * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ -export function createBackendModule( - config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), -): (...params: TOptions) => BackendFeature { - const configCallback = typeof config === 'function' ? config : () => config; - const factory: BackendFeatureFactory = (...options: TOptions) => { - const c = configCallback(...options); - +export function createBackendModule( + config: BackendModuleConfig, +): () => BackendFeature { + const factory: BackendFeatureFactory = () => { let registrations: InternalBackendModuleRegistration[]; return { @@ -200,7 +193,7 @@ export function createBackendModule( let init: InternalBackendModuleRegistration['init'] | undefined = undefined; - c.register({ + config.register({ registerExtensionPoint(ext, impl) { if (init) { throw new Error( @@ -222,15 +215,15 @@ export function createBackendModule( if (!init) { throw new Error( - `registerInit was not called by register in ${c.moduleId} module for ${c.pluginId}`, + `registerInit was not called by register in ${config.moduleId} module for ${config.pluginId}`, ); } registrations = [ { type: 'module', - pluginId: c.pluginId, - moduleId: c.moduleId, + pluginId: config.pluginId, + moduleId: config.moduleId, extensionPoints, init, }, diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index e2ed6ce387..d416ce7f9a 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -72,10 +72,8 @@ export interface BackendModuleRegistrationPoints { } /** @internal */ -export interface BackendFeatureFactory< - TOptions extends [options?: object] = [], -> { - (...options: TOptions): BackendFeature; +export interface BackendFeatureFactory { + (): BackendFeature; $$type: '@backstage/BackendFeatureFactory'; }