refactor: convert discovery services into feature loaders
Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-app-api': patch
|
||||
---
|
||||
|
||||
Deprecate the `featureDiscoveryServiceFactory` in favor of using `featureDiscoveryLoader` instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-dynamic-feature-service': patch
|
||||
---
|
||||
|
||||
Deprecate the `dynamicPluginsServiceRef`, `dynamicPluginsServiceFactory` and `dynamicPluginsServiceFactoryWithOptions` in favor of using `dynamicPluginsFeatureDiscoveryLoader` or `dynamicPluginsFeatureDiscoveryLoaderWithOptions` instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-plugin-api': patch
|
||||
---
|
||||
|
||||
Deprecate the `featureDiscoveryServiceRef` in favor of using `@backstage/backend-app-api#featureDiscoveryLoader` instead.
|
||||
@@ -3,10 +3,14 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { FeatureDiscoveryService } from '@backstage/backend-plugin-api/alpha';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @alpha (undocumented)
|
||||
// @public
|
||||
export const featureDiscoveryLoader: BackendFeature;
|
||||
|
||||
// @alpha @deprecated (undocumented)
|
||||
export const featureDiscoveryServiceFactory: ServiceFactory<
|
||||
FeatureDiscoveryService,
|
||||
'root',
|
||||
|
||||
@@ -14,4 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { featureDiscoveryServiceFactory } from './alpha/featureDiscoveryServiceFactory';
|
||||
export {
|
||||
featureDiscoveryLoader,
|
||||
featureDiscoveryServiceFactory,
|
||||
} from './alpha/featureDiscoveryServiceFactory';
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
RootConfigService,
|
||||
RootLoggerService,
|
||||
coreServices,
|
||||
createBackendFeatureLoader,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
@@ -153,7 +154,10 @@ class PackageDiscoveryService implements FeatureDiscoveryService {
|
||||
}
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated The `featureDiscoveryServiceFactory` is deprecated in favor of using {@link featureDiscoveryLoader} instead.
|
||||
*/
|
||||
export const featureDiscoveryServiceFactory = createServiceFactory({
|
||||
service: featureDiscoveryServiceRef,
|
||||
deps: {
|
||||
@@ -165,6 +169,36 @@ export const featureDiscoveryServiceFactory = createServiceFactory({
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* A loader that discovers backend features from the current package.json and its dependencies.
|
||||
*
|
||||
* @public
|
||||
*
|
||||
* @example
|
||||
* Using the `featureDiscoveryLoader` loader in a backend instance:
|
||||
* ```ts
|
||||
* //...
|
||||
* import { createBackend } from '@backstage/backend-defaults';
|
||||
* import { featureDiscoveryLoader } from '@backstage/backend-app-api';
|
||||
*
|
||||
* const backend = createBackend();
|
||||
* backend.add(featureDiscoveryLoader);
|
||||
* //...
|
||||
* backend.start();
|
||||
* ```
|
||||
*/
|
||||
export const featureDiscoveryLoader = createBackendFeatureLoader({
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
logger: coreServices.rootLogger,
|
||||
},
|
||||
async loader({ config, logger }) {
|
||||
const service = new PackageDiscoveryService(config, logger);
|
||||
const { features } = await service.getBackendFeatures();
|
||||
return features;
|
||||
},
|
||||
});
|
||||
|
||||
function isBackendFeature(value: unknown): value is BackendFeature {
|
||||
return (
|
||||
!!value &&
|
||||
|
||||
@@ -20,32 +20,23 @@ import { loggerServiceFactory } from '@backstage/backend-defaults/logger';
|
||||
import {
|
||||
createServiceRef,
|
||||
createServiceFactory,
|
||||
coreServices,
|
||||
createBackendPlugin,
|
||||
createBackendModule,
|
||||
createExtensionPoint,
|
||||
createBackendFeatureLoader,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { BackendInitializer } from './BackendInitializer';
|
||||
import { mockServices } from '@backstage/backend-test-utils';
|
||||
|
||||
class MockLogger {
|
||||
debug() {}
|
||||
info() {}
|
||||
warn() {}
|
||||
error() {}
|
||||
child() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
const requiredRootFactories = [
|
||||
mockServices.rootConfig.factory(),
|
||||
mockServices.rootLogger.factory(),
|
||||
];
|
||||
|
||||
const baseFactories = [
|
||||
...requiredRootFactories,
|
||||
lifecycleServiceFactory,
|
||||
rootLifecycleServiceFactory,
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLogger,
|
||||
deps: {},
|
||||
factory: () => new MockLogger(),
|
||||
}),
|
||||
loggerServiceFactory,
|
||||
];
|
||||
|
||||
@@ -399,7 +390,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should forward errors when plugins fail to start', async () => {
|
||||
const init = new BackendInitializer([]);
|
||||
const init = new BackendInitializer(requiredRootFactories);
|
||||
init.add(
|
||||
createBackendPlugin({
|
||||
pluginId: 'test',
|
||||
@@ -419,7 +410,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should forward errors when modules fail to start', async () => {
|
||||
const init = new BackendInitializer([]);
|
||||
const init = new BackendInitializer(requiredRootFactories);
|
||||
init.add(testPlugin);
|
||||
init.add(
|
||||
createBackendModule({
|
||||
@@ -441,7 +432,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should reject duplicate plugins', async () => {
|
||||
const init = new BackendInitializer([]);
|
||||
const init = new BackendInitializer(requiredRootFactories);
|
||||
init.add(
|
||||
createBackendPlugin({
|
||||
pluginId: 'test',
|
||||
@@ -470,7 +461,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should reject duplicate modules', async () => {
|
||||
const init = new BackendInitializer([]);
|
||||
const init = new BackendInitializer(requiredRootFactories);
|
||||
init.add(testPlugin);
|
||||
init.add(
|
||||
createBackendModule({
|
||||
@@ -505,12 +496,8 @@ describe('BackendInitializer', () => {
|
||||
const extA = createExtensionPoint<string>({ id: 'a' });
|
||||
const extB = createExtensionPoint<string>({ id: 'b' });
|
||||
const init = new BackendInitializer([
|
||||
...requiredRootFactories,
|
||||
rootLifecycleServiceFactory,
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLogger,
|
||||
deps: {},
|
||||
factory: () => new MockLogger(),
|
||||
}),
|
||||
]);
|
||||
init.add(testPlugin);
|
||||
init.add(
|
||||
|
||||
@@ -34,11 +34,11 @@ import type {
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import type { InternalServiceFactory } from '../../../backend-plugin-api/src/services/system/types';
|
||||
import { ForwardedError, ConflictError } from '@backstage/errors';
|
||||
import { featureDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha';
|
||||
import { DependencyGraph } from '../lib/DependencyGraph';
|
||||
import { ServiceRegistry } from './ServiceRegistry';
|
||||
import { createInitializationLogger } from './createInitializationLogger';
|
||||
import { unwrapFeature } from './helpers';
|
||||
import { featureDiscoveryLoader } from '../alpha/featureDiscoveryServiceFactory';
|
||||
|
||||
export interface BackendRegisterInit {
|
||||
consumes: Set<ServiceOrExtensionPoint>;
|
||||
@@ -150,25 +150,14 @@ export class BackendInitializer {
|
||||
}
|
||||
|
||||
async #doStart(): Promise<void> {
|
||||
this.add(featureDiscoveryLoader);
|
||||
|
||||
this.#serviceRegistry.checkForCircularDeps();
|
||||
|
||||
for (const feature of this.#registeredFeatures) {
|
||||
this.#addFeature(await feature);
|
||||
}
|
||||
|
||||
const featureDiscovery = await this.#serviceRegistry.get(
|
||||
featureDiscoveryServiceRef,
|
||||
'root',
|
||||
);
|
||||
|
||||
if (featureDiscovery) {
|
||||
const { features } = await featureDiscovery.getBackendFeatures();
|
||||
for (const feature of features) {
|
||||
this.#addFeature(unwrapFeature(feature));
|
||||
}
|
||||
this.#serviceRegistry.checkForCircularDeps();
|
||||
}
|
||||
|
||||
await this.#applyBackendFeatureLoaders(this.#registeredFeatureLoaders);
|
||||
|
||||
// Initialize all root scoped services
|
||||
|
||||
@@ -112,7 +112,15 @@ export interface DynamicPluginsFactoryOptions {
|
||||
moduleLoader?(logger: LoggerService): ModuleLoader;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const dynamicPluginsFeatureDiscoveryLoader: BackendFeature;
|
||||
|
||||
// @public
|
||||
export const dynamicPluginsFeatureDiscoveryLoaderWithOptions: (
|
||||
options?: DynamicPluginsFactoryOptions,
|
||||
) => BackendFeature;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const dynamicPluginsFeatureDiscoveryServiceFactory: ServiceFactory<
|
||||
FeatureDiscoveryService,
|
||||
'root',
|
||||
@@ -154,19 +162,19 @@ export const dynamicPluginsSchemasServiceFactoryWithOptions: (
|
||||
options?: DynamicPluginsSchemasOptions,
|
||||
) => ServiceFactory<DynamicPluginsSchemasService, 'root', 'singleton'>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const dynamicPluginsServiceFactory: ServiceFactory<
|
||||
DynamicPluginProvider,
|
||||
'root',
|
||||
'singleton'
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const dynamicPluginsServiceFactoryWithOptions: (
|
||||
options?: DynamicPluginsFactoryOptions,
|
||||
) => ServiceFactory<DynamicPluginProvider, 'root', 'singleton'>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const dynamicPluginsServiceRef: ServiceRef<
|
||||
DynamicPluginProvider,
|
||||
'root',
|
||||
|
||||
@@ -36,6 +36,8 @@ export {
|
||||
dynamicPluginsServiceFactory,
|
||||
dynamicPluginsServiceFactoryWithOptions,
|
||||
dynamicPluginsServiceRef,
|
||||
dynamicPluginsFeatureDiscoveryLoader,
|
||||
dynamicPluginsFeatureDiscoveryLoaderWithOptions,
|
||||
} from './plugin-manager';
|
||||
|
||||
export type {
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
BackendFeature,
|
||||
LoggerService,
|
||||
coreServices,
|
||||
createBackendFeatureLoader,
|
||||
createServiceFactory,
|
||||
createServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
@@ -214,6 +215,7 @@ export class DynamicPluginManager implements DynamicPluginProvider {
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated The `featureDiscoveryService` is deprecated in favor of using {@link dynamicPluginsFeatureDiscoveryLoader} or {@link dynamicPluginsFeatureDiscoveryLoaderWithOptions} instead.
|
||||
*/
|
||||
export const dynamicPluginsServiceRef = createServiceRef<DynamicPluginProvider>(
|
||||
{
|
||||
@@ -231,6 +233,7 @@ export interface DynamicPluginsFactoryOptions {
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link dynamicPluginsFeatureDiscoveryLoaderWithOptions} instead.
|
||||
*/
|
||||
export const dynamicPluginsServiceFactoryWithOptions = (
|
||||
options?: DynamicPluginsFactoryOptions,
|
||||
@@ -253,6 +256,7 @@ export const dynamicPluginsServiceFactoryWithOptions = (
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link dynamicPluginsFeatureDiscoveryLoader} instead.
|
||||
*/
|
||||
export const dynamicPluginsServiceFactory =
|
||||
dynamicPluginsServiceFactoryWithOptions();
|
||||
@@ -292,6 +296,7 @@ class DynamicPluginsEnabledFeatureDiscoveryService
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated The `featureDiscoveryService` is deprecated in favor of using {@link dynamicPluginsFeatureDiscoveryLoader} or {@link dynamicPluginsFeatureDiscoveryLoaderWithOptions} instead.
|
||||
*/
|
||||
export const dynamicPluginsFeatureDiscoveryServiceFactory =
|
||||
createServiceFactory({
|
||||
@@ -305,6 +310,69 @@ export const dynamicPluginsFeatureDiscoveryServiceFactory =
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* A function that returns a backend feature loader that uses the dynamic plugins system to discover features.
|
||||
*
|
||||
* @public
|
||||
*
|
||||
* @example
|
||||
* Using the `dynamicPluginsFeatureDiscoveryLoaderWithOptions` loader in a backend instance:
|
||||
* ```ts
|
||||
* //...
|
||||
* import { createBackend } from '@backstage/backend-defaults';
|
||||
* import { dynamicPluginsFeatureDiscoveryLoaderWithOptions } from '@backstage/backend-dynamic-feature-service';
|
||||
* import { myCustomModuleLoader } from './myCustomModuleLoader';
|
||||
*
|
||||
* const backend = createBackend();
|
||||
* backend.add(dynamicPluginsFeatureDiscoveryLoaderWithOptions({
|
||||
* moduleLoader: myCustomModuleLoader
|
||||
* }));
|
||||
* //...
|
||||
* backend.start();
|
||||
* ```
|
||||
*/
|
||||
export const dynamicPluginsFeatureDiscoveryLoaderWithOptions = (
|
||||
options?: DynamicPluginsFactoryOptions,
|
||||
) =>
|
||||
createBackendFeatureLoader({
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
logger: coreServices.rootLogger,
|
||||
},
|
||||
async loader({ config, logger }) {
|
||||
const manager = await DynamicPluginManager.create({
|
||||
config,
|
||||
logger,
|
||||
preferAlpha: true,
|
||||
moduleLoader: options?.moduleLoader?.(logger),
|
||||
});
|
||||
const service = new DynamicPluginsEnabledFeatureDiscoveryService(manager);
|
||||
const { features } = await service.getBackendFeatures();
|
||||
return features;
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* A backend feature loader that uses the dynamic plugins system to discover features.
|
||||
*
|
||||
* @public
|
||||
*
|
||||
* @example
|
||||
* Using the `dynamicPluginsFeatureDiscoveryLoader` loader in a backend instance:
|
||||
* ```ts
|
||||
* //...
|
||||
* import { createBackend } from '@backstage/backend-defaults';
|
||||
* import { dynamicPluginsFeatureDiscoveryLoader } from '@backstage/backend-dynamic-feature-service';
|
||||
*
|
||||
* const backend = createBackend();
|
||||
* backend.add(dynamicPluginsFeatureDiscoveryLoader);
|
||||
* //...
|
||||
* backend.start();
|
||||
* ```
|
||||
*/
|
||||
export const dynamicPluginsFeatureDiscoveryLoader =
|
||||
dynamicPluginsFeatureDiscoveryLoaderWithOptions();
|
||||
|
||||
function isBackendFeature(value: unknown): value is BackendFeature {
|
||||
return (
|
||||
!!value &&
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface FeatureDiscoveryService {
|
||||
}>;
|
||||
}
|
||||
|
||||
// @alpha
|
||||
// @alpha @deprecated
|
||||
export const featureDiscoveryServiceRef: ServiceRef<
|
||||
FeatureDiscoveryService,
|
||||
'root',
|
||||
|
||||
@@ -27,6 +27,7 @@ export interface FeatureDiscoveryService {
|
||||
/**
|
||||
* An optional service that can be used to dynamically load in additional BackendFeatures at runtime.
|
||||
* @alpha
|
||||
* @deprecated The `featureDiscoveryServiceRef` is deprecated in favor of using {@link @backstage/backend-app-api#featureDiscoveryLoader} instead.
|
||||
*/
|
||||
export const featureDiscoveryServiceRef =
|
||||
createServiceRef<FeatureDiscoveryService>({
|
||||
|
||||
Reference in New Issue
Block a user