From 015a6dced6f06d6108a1ed9526c9dc621d2f9b01 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 3 Jan 2023 11:39:44 +0100 Subject: [PATCH 1/5] backend-app-api: throw error if duplicate service implementations are provided Signed-off-by: Patrik Oldsberg --- .changeset/eleven-fans-love.md | 6 ++ .changeset/nine-falcons-appear.md | 5 ++ packages/backend-app-api/src/wiring/types.ts | 20 ++++++- .../src/CreateBackend.test.ts | 58 +++++++++++++++++++ .../backend-defaults/src/CreateBackend.ts | 38 +++++++----- .../src/next/wiring/TestBackend.test.ts | 55 +++++++++--------- .../src/next/wiring/TestBackend.ts | 5 +- 7 files changed, 142 insertions(+), 45 deletions(-) create mode 100644 .changeset/eleven-fans-love.md create mode 100644 .changeset/nine-falcons-appear.md create mode 100644 packages/backend-defaults/src/CreateBackend.test.ts diff --git a/.changeset/eleven-fans-love.md b/.changeset/eleven-fans-love.md new file mode 100644 index 0000000000..1b8f96be45 --- /dev/null +++ b/.changeset/eleven-fans-love.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-defaults': patch +--- + +Updated to make sure that service implementations replace default service implementations. diff --git a/.changeset/nine-falcons-appear.md b/.changeset/nine-falcons-appear.md new file mode 100644 index 0000000000..2011f4d992 --- /dev/null +++ b/.changeset/nine-falcons-appear.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +The `createSpecializedBackend` function will now throw an error if duplicate service implementations are provided. diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index 46ac690702..c591d5cb55 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -63,9 +63,25 @@ export interface EnumerableServiceHolder extends ServiceHolder { export function createSpecializedBackend( options: CreateSpecializedBackendOptions, ): Backend { - return new BackstageBackend( - options.services.map(s => (typeof s === 'function' ? s() : s)), + const services = options.services.map(sf => + typeof sf === 'function' ? sf() : sf, ); + + const exists = new Set(); + const duplicates = new Set(); + for (const { service } of services) { + if (exists.has(service.id)) { + duplicates.add(service.id); + } else { + exists.add(service.id); + } + } + if (duplicates.size > 0) { + const ids = Array.from(duplicates).join(', '); + throw new Error(`Duplicate service implementations provided for ${ids}`); + } + + return new BackstageBackend(services); } /** diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts new file mode 100644 index 0000000000..4b5e2e5848 --- /dev/null +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { createBackend } from './CreateBackend'; + +describe('createBackend', () => { + it('should not throw when overriding a default service implementation', () => { + expect(() => + createBackend({ + services: [ + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ addShutdownHook: () => {} }), + }), + ], + }), + ).not.toThrow(); + }); + + it('should throw on duplicate service implementations', () => { + expect(() => + createBackend({ + services: [ + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ addShutdownHook: () => {} }), + }), + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ addShutdownHook: () => {} }), + }), + ], + }), + ).toThrow( + 'Duplicate service implementations provided for core.rootLifecycle', + ); + }); +}); diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index 20edfc85a8..6f9e8e39b6 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -35,20 +35,20 @@ import { import { ServiceFactory } from '@backstage/backend-plugin-api'; export const defaultServiceFactories = [ - cacheFactory, - configFactory, - databaseFactory, - discoveryFactory, - loggerFactory, - rootLoggerFactory, - permissionsFactory, - schedulerFactory, - tokenManagerFactory, - urlReaderFactory, - httpRouterFactory, - rootHttpRouterFactory, - lifecycleFactory, - rootLifecycleFactory, + cacheFactory(), + configFactory(), + databaseFactory(), + discoveryFactory(), + loggerFactory(), + rootLoggerFactory(), + permissionsFactory(), + schedulerFactory(), + tokenManagerFactory(), + urlReaderFactory(), + httpRouterFactory(), + rootHttpRouterFactory(), + lifecycleFactory(), + rootLifecycleFactory(), ]; /** @@ -62,7 +62,15 @@ export interface CreateBackendOptions { * @public */ export function createBackend(options?: CreateBackendOptions): Backend { + const providedServices = (options?.services ?? []).map(sf => + typeof sf === 'function' ? sf() : sf, + ); + const providedIds = new Set(providedServices.map(sf => sf.service.id)); + const neededDefaultFactories = defaultServiceFactories.filter( + sf => !providedIds.has(sf.service.id), + ); + return createSpecializedBackend({ - services: [...defaultServiceFactories, ...(options?.services ?? [])], + services: [...neededDefaultFactories, ...providedServices], }); } diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index 3cc8507df3..5ea37e9106 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -64,33 +64,34 @@ describe('TestBackend', () => { const extensionPoint3 = createExtensionPoint({ id: 'b3' }); const extensionPoint4 = createExtensionPoint({ id: 'b4' }); const extensionPoint5 = createExtensionPoint({ id: 'b5' }); - await startTestBackend({ - services: [ - // @ts-expect-error - [extensionPoint1, { a: 'a' }], - [serviceRef, { a: 'a' }], - [serviceRef, { a: 'a', b: 'b' }], - // @ts-expect-error - [serviceRef, { c: 'c' }], - // @ts-expect-error - [serviceRef, { a: 'a', c: 'c' }], - // @ts-expect-error - [serviceRef, { a: 'a', b: 'b', c: 'c' }], - ], - extensionPoints: [ - // @ts-expect-error - [serviceRef, { a: 'a' }], - [extensionPoint1, { a: 'a' }], - [extensionPoint2, { a: 'a', b: 'b' }], - // @ts-expect-error - [extensionPoint3, { c: 'c' }], - // @ts-expect-error - [extensionPoint4, { a: 'a', c: 'c' }], - // @ts-expect-error - [extensionPoint5, { a: 'a', b: 'b', c: 'c' }], - ], - }); - expect(1).toBe(1); + await expect( + startTestBackend({ + services: [ + // @ts-expect-error + [extensionPoint1, { a: 'a' }], + [serviceRef, { a: 'a' }], + [serviceRef, { a: 'a', b: 'b' }], + // @ts-expect-error + [serviceRef, { c: 'c' }], + // @ts-expect-error + [serviceRef, { a: 'a', c: 'c' }], + // @ts-expect-error + [serviceRef, { a: 'a', b: 'b', c: 'c' }], + ], + extensionPoints: [ + // @ts-expect-error + [serviceRef, { a: 'a' }], + [extensionPoint1, { a: 'a' }], + [extensionPoint2, { a: 'a', b: 'b' }], + // @ts-expect-error + [extensionPoint3, { c: 'c' }], + // @ts-expect-error + [extensionPoint4, { a: 'a', c: 'c' }], + // @ts-expect-error + [extensionPoint5, { a: 'a', b: 'b', c: 'c' }], + ], + }), + ).rejects.toThrow(); }); it('should start the test backend', async () => { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index 647ebc9dda..0295332855 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -93,11 +93,14 @@ export async function startTestBackend< factory: async () => impl, })(); } + if (typeof serviceDef === 'function') { + return serviceDef(); + } return serviceDef as ServiceFactory; }); for (const factory of defaultServiceFactories) { - if (!factories.some(f => f.service === factory.service)) { + if (!factories.some(f => f.service.id === factory.service.id)) { factories.push(factory); } } From f10618848119199f53e9f51b0d58b7da4737f225 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 3 Jan 2023 11:44:33 +0100 Subject: [PATCH 2/5] backend-app-api: simplified service registry construction Signed-off-by: Patrik Oldsberg --- .../src/wiring/BackendInitializer.test.ts | 4 ++-- .../src/wiring/ServiceRegistry.test.ts | 22 +++++++++---------- .../src/wiring/ServiceRegistry.ts | 14 ++---------- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts index 8fd7441c37..c00969a52c 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts @@ -40,12 +40,12 @@ describe('BackendInitializer', () => { service: rootRef, deps: {}, factory: rootFactory, - }), + })(), createServiceFactory({ service: pluginRef, deps: {}, factory: pluginFactory, - }), + })(), ]); const init = new BackendInitializer(registry); diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts index b878a6a75d..9348f59d64 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts @@ -33,7 +33,7 @@ const sf1 = createServiceFactory({ return { x: 1 }; }; }, -}); +})(); const ref2 = createServiceRef<{ x: number }>({ scope: 'root', @@ -45,7 +45,7 @@ const sf2 = createServiceFactory({ async factory() { return { x: 2 }; }, -}); +})(); const sf2b = createServiceFactory({ service: ref2, deps: {}, @@ -133,7 +133,7 @@ describe('ServiceRegistry', () => { return { x: 2 }; }, }); - const registry = new ServiceRegistry([factory, sf1]); + const registry = new ServiceRegistry([factory(), sf1]); await expect(registry.get(ref2, 'catalog')).rejects.toThrow( "Failed to instantiate 'root' scoped service '2' because it depends on 'plugin' scoped service '1'.", ); @@ -147,7 +147,7 @@ describe('ServiceRegistry', () => { return async () => ({ x: rootDep.x }); }, }); - const registry = new ServiceRegistry([factory, sf2]); + const registry = new ServiceRegistry([factory(), sf2]); await expect(registry.get(ref1, 'catalog')).resolves.toEqual({ x: 2, }); @@ -162,7 +162,7 @@ describe('ServiceRegistry', () => { return { x: rootDep.x }; }, }); - const registry = new ServiceRegistry([factory, sf2]); + const registry = new ServiceRegistry([factory(), sf2]); await expect(registry.get(ref, 'catalog')).resolves.toEqual({ x: 2, }); @@ -177,7 +177,7 @@ describe('ServiceRegistry', () => { return async ({ meta }) => ({ pluginId: meta.getId() }); }, }); - const registry = new ServiceRegistry([factory]); + const registry = new ServiceRegistry([factory()]); await expect(registry.get(ref, 'catalog')).resolves.toEqual({ pluginId: 'catalog', }); @@ -257,7 +257,7 @@ describe('ServiceRegistry', () => { factory, }); - const registry = new ServiceRegistry([myFactory]); + const registry = new ServiceRegistry([myFactory()]); await Promise.all([ registry.get(ref1, 'catalog')!, @@ -280,7 +280,7 @@ describe('ServiceRegistry', () => { }, }); - const registry = new ServiceRegistry([myFactory]); + const registry = new ServiceRegistry([myFactory()]); await expect(registry.get(ref1, 'catalog')).rejects.toThrow( "Failed to instantiate service '1' for 'catalog' because the following dependent services are missing: '2'", @@ -309,7 +309,7 @@ describe('ServiceRegistry', () => { }, }); - const registry = new ServiceRegistry([factoryA, factoryB]); + const registry = new ServiceRegistry([factoryA(), factoryB()]); await expect(registry.get(refA, 'catalog')).rejects.toThrow( "Failed to instantiate service 'a' for 'catalog' because the factory function threw an error, Error: Failed to instantiate service 'b' for 'catalog' because the following dependent services are missing: 'c', 'd'", @@ -325,7 +325,7 @@ describe('ServiceRegistry', () => { }, }); - const registry = new ServiceRegistry([myFactory]); + const registry = new ServiceRegistry([myFactory()]); await expect(registry.get(ref1, 'catalog')).rejects.toThrow( "Failed to instantiate service '1' because the top-level factory function threw an error, Error: top-level error", @@ -343,7 +343,7 @@ describe('ServiceRegistry', () => { }, }); - const registry = new ServiceRegistry([myFactory]); + const registry = new ServiceRegistry([myFactory()]); await expect(registry.get(ref1, 'catalog')).rejects.toThrow( "Failed to instantiate service '1' for 'catalog' because the factory function threw an error, Error: error in plugin", diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.ts index 208e5cf260..b4d75dac1a 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.ts @@ -44,18 +44,8 @@ export class ServiceRegistry implements EnumerableServiceHolder { } >; - constructor( - factories: Array | (() => ServiceFactory)>, - ) { - this.#providedFactories = new Map( - factories.map(f => { - if (typeof f === 'function') { - const cf = f(); - return [cf.service.id, cf]; - } - return [f.service.id, f]; - }), - ); + constructor(factories: Array>) { + this.#providedFactories = new Map(factories.map(f => [f.service.id, f])); this.#loadedDefaultFactories = new Map(); this.#implementations = new Map(); } From 150a7dd7909a7e88ca07c116613e0f73bca4fa9d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 3 Jan 2023 11:50:31 +0100 Subject: [PATCH 3/5] backend-app-api: throw error if trying to override metadata service Signed-off-by: Patrik Oldsberg --- .changeset/great-forks-lay.md | 5 +++++ packages/backend-app-api/src/wiring/types.ts | 6 ++++++ .../backend-defaults/src/CreateBackend.test.ts | 14 ++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 .changeset/great-forks-lay.md diff --git a/.changeset/great-forks-lay.md b/.changeset/great-forks-lay.md new file mode 100644 index 0000000000..6585951062 --- /dev/null +++ b/.changeset/great-forks-lay.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +An error will now be thrown if attempting to override the plugin metadata service. diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index c591d5cb55..d3ffef731c 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -19,6 +19,7 @@ import { BackendFeature, ExtensionPoint, ServiceRef, + coreServices, } from '@backstage/backend-plugin-api'; import { BackstageBackend } from './BackstageBackend'; @@ -80,6 +81,11 @@ export function createSpecializedBackend( const ids = Array.from(duplicates).join(', '); throw new Error(`Duplicate service implementations provided for ${ids}`); } + if (exists.has(coreServices.pluginMetadata.id)) { + throw new Error( + `The ${coreServices.pluginMetadata.id} service cannot be overridden`, + ); + } return new BackstageBackend(services); } diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index 4b5e2e5848..a05e09df0f 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -55,4 +55,18 @@ describe('createBackend', () => { 'Duplicate service implementations provided for core.rootLifecycle', ); }); + + it('should throw when providing a plugin metadata service implementation', () => { + expect(() => + createBackend({ + services: [ + createServiceFactory({ + service: coreServices.pluginMetadata, + deps: {}, + factory: async () => async () => ({ getId: () => 'test' }), + }), + ], + }), + ).toThrow('The core.plugin-metadata service cannot be overridden'); + }); }); From 4cadd628b360c94b154178a92b0b6bcaed6081ee Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 3 Jan 2023 11:50:49 +0100 Subject: [PATCH 4/5] backend-app-api: extract and add tests for createSpecializedBackend Signed-off-by: Patrik Oldsberg --- .../wiring/createSpecializedBackend.test.ts | 62 +++++++++++++++++++ .../src/wiring/createSpecializedBackend.ts | 51 +++++++++++++++ packages/backend-app-api/src/wiring/index.ts | 2 +- packages/backend-app-api/src/wiring/types.ts | 36 +---------- 4 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts create mode 100644 packages/backend-app-api/src/wiring/createSpecializedBackend.ts diff --git a/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts b/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts new file mode 100644 index 0000000000..7561e229a2 --- /dev/null +++ b/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { createSpecializedBackend } from './createSpecializedBackend'; + +describe('createSpecializedBackend', () => { + it('should create a backend without services', () => { + expect(() => createSpecializedBackend({ services: [] })).not.toThrow(); + }); + + it('should throw on duplicate service implementations', () => { + expect(() => + createSpecializedBackend({ + services: [ + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ addShutdownHook: () => {} }), + }), + createServiceFactory({ + service: coreServices.rootLifecycle, + deps: {}, + factory: async () => ({ addShutdownHook: () => {} }), + }), + ], + }), + ).toThrow( + 'Duplicate service implementations provided for core.rootLifecycle', + ); + }); + + it('should throw when providing a plugin metadata service implementation', () => { + expect(() => + createSpecializedBackend({ + services: [ + createServiceFactory({ + service: coreServices.pluginMetadata, + deps: {}, + factory: async () => async () => ({ getId: () => 'test' }), + }), + ], + }), + ).toThrow('The core.plugin-metadata service cannot be overridden'); + }); +}); diff --git a/packages/backend-app-api/src/wiring/createSpecializedBackend.ts b/packages/backend-app-api/src/wiring/createSpecializedBackend.ts new file mode 100644 index 0000000000..15e51f7c4c --- /dev/null +++ b/packages/backend-app-api/src/wiring/createSpecializedBackend.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { coreServices } from '@backstage/backend-plugin-api'; +import { BackstageBackend } from './BackstageBackend'; +import { Backend, CreateSpecializedBackendOptions } from './types'; + +/** + * @public + */ +export function createSpecializedBackend( + options: CreateSpecializedBackendOptions, +): Backend { + const services = options.services.map(sf => + typeof sf === 'function' ? sf() : sf, + ); + + const exists = new Set(); + const duplicates = new Set(); + for (const { service } of services) { + if (exists.has(service.id)) { + duplicates.add(service.id); + } else { + exists.add(service.id); + } + } + if (duplicates.size > 0) { + const ids = Array.from(duplicates).join(', '); + throw new Error(`Duplicate service implementations provided for ${ids}`); + } + if (exists.has(coreServices.pluginMetadata.id)) { + throw new Error( + `The ${coreServices.pluginMetadata.id} service cannot be overridden`, + ); + } + + return new BackstageBackend(services); +} diff --git a/packages/backend-app-api/src/wiring/index.ts b/packages/backend-app-api/src/wiring/index.ts index 2f55076922..6e0fb272ae 100644 --- a/packages/backend-app-api/src/wiring/index.ts +++ b/packages/backend-app-api/src/wiring/index.ts @@ -19,4 +19,4 @@ export type { CreateSpecializedBackendOptions, ServiceOrExtensionPoint, } from './types'; -export { createSpecializedBackend } from './types'; +export { createSpecializedBackend } from './createSpecializedBackend'; diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index d3ffef731c..115488d596 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -15,13 +15,11 @@ */ import { - ServiceFactory, BackendFeature, ExtensionPoint, + ServiceFactory, ServiceRef, - coreServices, } from '@backstage/backend-plugin-api'; -import { BackstageBackend } from './BackstageBackend'; /** * @public @@ -58,38 +56,6 @@ export interface EnumerableServiceHolder extends ServiceHolder { getServiceRefs(): ServiceRef[]; } -/** - * @public - */ -export function createSpecializedBackend( - options: CreateSpecializedBackendOptions, -): Backend { - const services = options.services.map(sf => - typeof sf === 'function' ? sf() : sf, - ); - - const exists = new Set(); - const duplicates = new Set(); - for (const { service } of services) { - if (exists.has(service.id)) { - duplicates.add(service.id); - } else { - exists.add(service.id); - } - } - if (duplicates.size > 0) { - const ids = Array.from(duplicates).join(', '); - throw new Error(`Duplicate service implementations provided for ${ids}`); - } - if (exists.has(coreServices.pluginMetadata.id)) { - throw new Error( - `The ${coreServices.pluginMetadata.id} service cannot be overridden`, - ); - } - - return new BackstageBackend(services); -} - /** * @public */ From dd9f7b8b242f64b3a4da03d2ddc25501f2c747a8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 7 Jan 2023 14:24:04 +0100 Subject: [PATCH 5/5] update plugin metadata service ID in tests Signed-off-by: Patrik Oldsberg --- .../backend-app-api/src/wiring/createSpecializedBackend.test.ts | 2 +- packages/backend-defaults/src/CreateBackend.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts b/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts index 7561e229a2..c670613657 100644 --- a/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts +++ b/packages/backend-app-api/src/wiring/createSpecializedBackend.test.ts @@ -57,6 +57,6 @@ describe('createSpecializedBackend', () => { }), ], }), - ).toThrow('The core.plugin-metadata service cannot be overridden'); + ).toThrow('The core.pluginMetadata service cannot be overridden'); }); }); diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index a05e09df0f..89a8e96b28 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -67,6 +67,6 @@ describe('createBackend', () => { }), ], }), - ).toThrow('The core.plugin-metadata service cannot be overridden'); + ).toThrow('The core.pluginMetadata service cannot be overridden'); }); });