From 0c450c0e9e44571cb6f8139d6b8a3331eb1dfc6d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 1 Aug 2023 11:55:25 +0200 Subject: [PATCH] add feature discovery service Co-authored-by: Patrik Oldsberg Signed-off-by: Vincenzo Scamporlino --- .../src/wiring/BackendInitializer.ts | 17 +++++++++++ packages/backend-plugin-api/package.json | 19 ++++++++++-- packages/backend-plugin-api/src/alpha.ts | 29 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 packages/backend-plugin-api/src/alpha.ts diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index ec4b2a79ac..cf140158a6 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -27,6 +27,7 @@ import { EnumerableServiceHolder, ServiceOrExtensionPoint } from './types'; // eslint-disable-next-line @backstage/no-forbidden-package-imports import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types'; import { ForwardedError } from '@backstage/errors'; +import { featureDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha'; export interface BackendRegisterInit { consumes: Set; @@ -87,6 +88,10 @@ export class BackendInitializer { if (this.#startPromise) { throw new Error('feature can not be added after the backend has started'); } + this.#addFeature(feature); + } + + #addFeature(feature: BackendFeature) { if (feature.$$type !== '@backstage/BackendFeature') { throw new Error( `Failed to add feature, invalid type '${feature.$$type}'`, @@ -129,6 +134,18 @@ export class BackendInitializer { } async #doStart(): Promise { + const featureDiscovery = await this.#serviceHolder.get( + featureDiscoveryServiceRef, + 'root', + ); + + if (featureDiscovery) { + const { features } = await featureDiscovery.getBackendFeatures(); + for (const plugin of features) { + this.#addFeature(plugin); + } + } + // Initialize all root scoped services for (const ref of this.#serviceHolder.getServiceRefs()) { if (ref.scope === 'root') { diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 5d0bfe08fb..555c60c8e4 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -5,13 +5,26 @@ "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" }, "backstage": { "role": "node-library" }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.ts" + ], + "package.json": [ + "package.json" + ] + } + }, "homepage": "https://backstage.io", "repository": { "type": "git", diff --git a/packages/backend-plugin-api/src/alpha.ts b/packages/backend-plugin-api/src/alpha.ts new file mode 100644 index 0000000000..6db9b009cf --- /dev/null +++ b/packages/backend-plugin-api/src/alpha.ts @@ -0,0 +1,29 @@ +/* + * 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 { createServiceRef } from './services'; +import { BackendFeature } from './wiring'; + +/** @alpha */ +export interface FeatureDiscoveryService { + getBackendFeatures(): Promise<{ features: Array }>; +} + +/** @alpha */ +export const featureDiscoveryServiceRef = + createServiceRef({ + id: 'core.featureDiscovery', + });