define BackendFeatureFactory

Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com>
This commit is contained in:
Vincenzo Scamporlino
2023-08-01 20:43:28 +02:00
committed by Philipp Hugenroth
parent 0b4dbb4082
commit 36a40b4903
4 changed files with 51 additions and 23 deletions
+32 -16
View File
@@ -16,6 +16,7 @@
import {
BackendFeature,
BackendFeatureFactory,
RootConfigService,
coreServices,
createServiceFactory,
@@ -71,8 +72,11 @@ export class PackageDiscoveryService implements FeatureDiscoveryService {
throw new Error('NOOOOOOOOOOOOOOOOOOOOOOOOOO');
}
console.log(`DEBUG: packageDir=`, packageDir);
const { dependencies } = require(resolvePath(packageDir, 'package.json'));
const dependencyNames = Object.keys(dependencies);
const { dependencies } = require(resolvePath(
packageDir,
'package.json',
)) as BackstagePackageJson;
const dependencyNames = Object.keys(dependencies || {});
console.log(`DEBUG: dependencyNames=`, dependencyNames);
const features: BackendFeature[] = [];
@@ -82,23 +86,16 @@ export class PackageDiscoveryService implements FeatureDiscoveryService {
if (!LOADED_PACKAGE_ROLES.includes(depPkg?.backstage?.role ?? '')) {
continue;
}
const depModule = require(name); // @backstage/plugin-catalog-backend
const depModule = require(name);
console.log(`DEBUG: loaded ${name} depModule=`, depModule);
Object.values(depModule).filter(exportValue => {
if (
exportValue &&
typeof exportValue === 'object' &&
(exportValue as any).$$type === '@backstage/BackendFeature'
) {
features.push(exportValue as BackendFeature);
for (const exportValue of Object.values(depModule)) {
if (isBackendFeature(exportValue)) {
features.push(exportValue);
}
if (
typeof exportValue === 'function' &&
(exportValue as any).$$type === '@backstage/BackendFeatureFactory'
) {
features.push(exportValue() as BackendFeature);
if (isBackendFeatureFactory(exportValue)) {
features.push(exportValue());
}
});
}
}
console.log(`DEBUG: features=`, features);
@@ -116,3 +113,22 @@ export const packageFeatureDiscoveryServiceFactory = createServiceFactory({
return new PackageDiscoveryService(config);
},
});
function isBackendFeature(value: unknown): value is BackendFeature {
return (
!!value &&
typeof value === 'object' &&
(value as BackendFeature).$$type === '@backstage/BackendFeature'
);
}
function isBackendFeatureFactory(
value: unknown,
): value is BackendFeatureFactory {
return (
!!value &&
typeof value === 'object' &&
(value as BackendFeatureFactory).$$type ===
'@backstage/BackendFeatureFactory'
);
}
@@ -17,11 +17,10 @@
import {
BackendModuleRegistrationPoints,
BackendPluginRegistrationPoints,
BackendFeature,
ExtensionPoint,
InternalBackendFeature,
InternalBackendModuleRegistration,
InternalBackendPluginRegistration,
BackendFeatureFactory,
} from './types';
/**
@@ -92,9 +91,10 @@ export const catalogPlugin = createBackendPlugin({
*/
export function createBackendPlugin<TOptions extends [options?: object] = []>(
config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig),
): (...params: TOptions) => BackendFeature {
): BackendFeatureFactory<TOptions> {
const configCallback = typeof config === 'function' ? config : () => config;
const factory = (...options: TOptions): InternalBackendFeature => {
const factory: BackendFeatureFactory<TOptions> = (...options) => {
const c = configCallback(...options);
let registrations: InternalBackendPluginRegistration[];
@@ -149,8 +149,8 @@ export function createBackendPlugin<TOptions extends [options?: object] = []>(
},
};
};
factory.$$type = '@backstage/BackendFeatureFactory';
return factory;
}
@@ -184,9 +184,9 @@ export interface BackendModuleConfig {
*/
export function createBackendModule<TOptions extends [options?: object] = []>(
config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig),
): (...params: TOptions) => BackendFeature {
): BackendFeatureFactory<TOptions> {
const configCallback = typeof config === 'function' ? config : () => config;
return (...options: TOptions): InternalBackendFeature => {
const factory: BackendFeatureFactory<TOptions> = (...options: TOptions) => {
const c = configCallback(...options);
let registrations: InternalBackendModuleRegistration[];
@@ -231,4 +231,7 @@ export function createBackendModule<TOptions extends [options?: object] = []>(
},
};
};
factory.$$type = '@backstage/BackendFeatureFactory';
return factory;
}
@@ -28,5 +28,6 @@ export type {
BackendModuleRegistrationPoints,
BackendPluginRegistrationPoints,
BackendFeature,
BackendFeatureFactory,
ExtensionPoint,
} from './types';
@@ -67,6 +67,14 @@ export interface BackendModuleRegistrationPoints {
}): void;
}
/** @public */
export interface BackendFeatureFactory<
TOptions extends [options?: object] = [],
> {
(...options: TOptions): BackendFeature;
$$type: '@backstage/BackendFeatureFactory';
}
/** @public */
export interface BackendFeature {
// NOTE: This type is opaque in order to simplify future API evolution.