diff --git a/packages/backend-plugin-api/src/services/system/types.test.ts b/packages/backend-plugin-api/src/services/system/types.test.ts index adf097761b..32c1774455 100644 --- a/packages/backend-plugin-api/src/services/system/types.test.ts +++ b/packages/backend-plugin-api/src/services/system/types.test.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -import { createServiceFactory, createServiceRef } from './types'; +import { + InternalServiceFactory, + createServiceFactory, + createServiceRef, +} from './types'; const ref = createServiceRef({ id: 'x' }); const rootDep = createServiceRef({ id: 'y', scope: 'root' }); @@ -36,6 +40,10 @@ describe('createServiceFactory', () => { }, }); expect(metaFactory).toEqual(expect.any(Function)); + expect(metaFactory().$$type).toBe('@backstage/BackendFeature'); + expect((metaFactory() as InternalServiceFactory).featureType).toBe( + 'service', + ); expect(metaFactory().service).toBe(ref); // @ts-expect-error diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index d31350806d..ccec36e39a 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -78,6 +78,7 @@ export interface InternalServiceFactory< TScope extends 'plugin' | 'root' = 'plugin' | 'root', > extends ServiceFactory { version: 'v1'; + featureType: 'service'; initialization?: 'always' | 'lazy'; deps: { [key in string]: ServiceRef }; createRootContext?(deps: { [key in string]: unknown }): Promise; @@ -307,6 +308,7 @@ export function createServiceFactory< return { $$type: '@backstage/BackendFeature', version: 'v1', + featureType: 'service', service: c.service, initialization: c.initialization, deps: c.deps, @@ -322,6 +324,7 @@ export function createServiceFactory< return { $$type: '@backstage/BackendFeature', version: 'v1', + featureType: 'service', service: c.service, initialization: c.initialization, ...('createRootContext' in c diff --git a/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.test.ts b/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.test.ts index 98471bef4c..37fc079551 100644 --- a/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.test.ts +++ b/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.test.ts @@ -15,33 +15,25 @@ */ import { coreServices, createServiceFactory } from '../services'; +import { InternalServiceFactory } from '../services/system/types'; import { BackendFeature } from '../types'; import { createBackendFeatureLoader } from './createBackendFeatureLoader'; import { createBackendPlugin } from './createBackendPlugin'; -import { - InternalBackendFeature, - InternalBackendFeatureLoaderRegistration, -} from './types'; +import { InternalBackendFeatureLoader } from './types'; describe('createBackendFeatureLoader', () => { it('should create an empty feature loader', () => { const result = createBackendFeatureLoader({ deps: {}, loader: () => [], - }); + }) as InternalBackendFeatureLoader; - const plugin = result as unknown as InternalBackendFeature; - expect(plugin.$$type).toEqual('@backstage/BackendFeature'); - expect(plugin.version).toEqual('v1'); - expect(plugin.getRegistrations).toEqual(expect.any(Function)); - expect(plugin.getRegistrations()).toEqual([ - { - type: 'loader', - description: expect.stringMatching(/^created at '.*'$/), - deps: expect.any(Object), - loader: expect.any(Function), - }, - ]); + expect(result.$$type).toEqual('@backstage/BackendFeature'); + expect(result.version).toEqual('v1'); + expect(result.featureType).toEqual('loader'); + expect(result.deps).toEqual({}); + expect(result.loader).toEqual(expect.any(Function)); + expect(result.description).toMatch(/^created at '.*'$/); }); it('should create a feature loader that loads a few features', async () => { @@ -69,29 +61,21 @@ describe('createBackendFeatureLoader', () => { }), ]; }, - }) as InternalBackendFeature; + }) as InternalBackendFeatureLoader; expect(result.$$type).toEqual('@backstage/BackendFeature'); expect(result.version).toEqual('v1'); - expect(result.getRegistrations).toEqual(expect.any(Function)); + expect(result.featureType).toEqual('loader'); - const registrations = result.getRegistrations(); - expect(registrations).toEqual([ - { - type: 'loader', - description: expect.stringMatching(/^created at '.*'$/), - deps: expect.any(Object), - loader: expect.any(Function), - }, - ]); - - const results = await (registrations[0] as any).loader({ config: {} }); + const results = await result.loader({ config: {} }); expect(results.length).toBe(3); const [pluginX, serviceFactory, pluginY] = results; expect(pluginX.$$type).toBe('@backstage/BackendFeature'); expect(serviceFactory.$$type).toBe('@backstage/BackendFeature'); expect(pluginY.$$type).toBe('@backstage/BackendFeature'); - expect(serviceFactory.service.id).toBe(coreServices.pluginMetadata.id); + expect((serviceFactory as InternalServiceFactory).service.id).toBe( + coreServices.pluginMetadata.id, + ); }); it('should support multiple output formats', async () => { @@ -99,10 +83,8 @@ describe('createBackendFeatureLoader', () => { const dynamicFeature = Promise.resolve({ default: feature }); async function extractResult(f: BackendFeature) { - const internal = f as InternalBackendFeature; - const reg = - internal.getRegistrations()[0] as InternalBackendFeatureLoaderRegistration; - return reg.loader({}); + const internal = f as InternalBackendFeatureLoader; + return internal.loader({}); } await expect( diff --git a/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.ts b/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.ts index 9722cc534f..de26b5154d 100644 --- a/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.ts +++ b/packages/backend-plugin-api/src/wiring/createBackendFeatureLoader.ts @@ -16,7 +16,7 @@ import { ServiceRef } from '../services'; import { BackendFeature } from '../types'; -import { InternalBackendFeature } from './types'; +import { InternalBackendFeatureLoader } from './types'; /** * @public @@ -43,31 +43,25 @@ export interface CreateBackendFeatureLoaderOptions< export function createBackendFeatureLoader< TDeps extends { [name in string]: unknown }, >(options: CreateBackendFeatureLoaderOptions): BackendFeature { - const registrations = [ - { - type: 'loader', - description: `created at '${new Date().toISOString()}'`, - deps: options.deps, - async loader(deps: TDeps) { - const it = await options.loader(deps); - const result = new Array(); - for await (const item of it) { - if ('$$type' in item && item.$$type === '@backstage/BackendFeature') { - result.push(item); - } else if ('default' in item) { - result.push(item.default); - } else { - throw new Error(`Invalid item "${item}"`); - } - } - return result; - }, - }, - ]; - return { $$type: '@backstage/BackendFeature', version: 'v1', - getRegistrations: () => registrations, - } as InternalBackendFeature; + featureType: 'loader', + description: `created at '${new Date().toISOString()}'`, + deps: options.deps, + async loader(deps: TDeps) { + const it = await options.loader(deps); + const result = new Array(); + for await (const item of it) { + if ('$$type' in item && item.$$type === '@backstage/BackendFeature') { + result.push(item); + } else if ('default' in item) { + result.push(item.default); + } else { + throw new Error(`Invalid item "${item}"`); + } + } + return result; + }, + } as InternalBackendFeatureLoader; } diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index 7569cc2b41..df0ca93089 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -75,10 +75,9 @@ export interface BackendModuleRegistrationPoints { /** @internal */ export interface InternalBackendFeature extends BackendFeature { version: 'v1'; + featureType: 'registrations'; getRegistrations(): Array< - | InternalBackendPluginRegistration - | InternalBackendModuleRegistration - | InternalBackendFeatureLoaderRegistration + InternalBackendPluginRegistration | InternalBackendModuleRegistration >; } @@ -108,8 +107,9 @@ export interface InternalBackendModuleRegistration { /** * @public */ -export interface InternalBackendFeatureLoaderRegistration { - type: 'loader'; +export interface InternalBackendFeatureLoader extends BackendFeature { + version: 'v1'; + featureType: 'loader'; description: string; deps: Record>; loader(deps: Record): Promise;