backend-plugin-api: allow modules to register extension points
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/backend-plugin-api': patch
|
||||
'@backstage/backend-app-api': patch
|
||||
---
|
||||
|
||||
Allow modules to register extension points.
|
||||
@@ -161,7 +161,7 @@ export class BackendInitializer {
|
||||
for (const r of feature.getRegistrations()) {
|
||||
const provides = new Set<ExtensionPoint<unknown>>();
|
||||
|
||||
if (r.type === 'plugin') {
|
||||
if (r.type === 'plugin' || r.type === 'module') {
|
||||
for (const [extRef, extImpl] of r.extensionPoints) {
|
||||
if (this.#extensionPoints.has(extRef)) {
|
||||
throw new Error(
|
||||
|
||||
@@ -31,6 +31,11 @@ export interface BackendModuleConfig {
|
||||
|
||||
// @public
|
||||
export interface BackendModuleRegistrationPoints {
|
||||
// (undocumented)
|
||||
registerExtensionPoint<TExtensionPoint>(
|
||||
ref: ExtensionPoint<TExtensionPoint>,
|
||||
impl: TExtensionPoint,
|
||||
): void;
|
||||
// (undocumented)
|
||||
registerInit<
|
||||
Deps extends {
|
||||
|
||||
@@ -149,6 +149,7 @@ describe('createBackendModule', () => {
|
||||
type: 'module',
|
||||
pluginId: 'x',
|
||||
moduleId: 'y',
|
||||
extensionPoints: [],
|
||||
init: {
|
||||
deps: expect.any(Object),
|
||||
func: expect.any(Function),
|
||||
|
||||
@@ -159,13 +159,14 @@ export function createBackendPlugin<TOptions extends [options?: object] = []>(
|
||||
*/
|
||||
export interface BackendModuleConfig {
|
||||
/**
|
||||
* The ID of this plugin.
|
||||
* Should exactly match the `id` of the plugin that the module extends.
|
||||
*
|
||||
* @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
|
||||
*/
|
||||
pluginId: string;
|
||||
|
||||
/**
|
||||
* Should exactly match the `id` of the plugin that the module extends.
|
||||
* The ID of this module, used to identify the module and ensure that it is not installed twice.
|
||||
*/
|
||||
moduleId: string;
|
||||
register(reg: BackendModuleRegistrationPoints): void;
|
||||
@@ -194,10 +195,20 @@ export function createBackendModule<TOptions extends [options?: object] = []>(
|
||||
if (registrations) {
|
||||
return registrations;
|
||||
}
|
||||
const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =
|
||||
[];
|
||||
let init: InternalBackendModuleRegistration['init'] | undefined =
|
||||
undefined;
|
||||
|
||||
c.register({
|
||||
registerExtensionPoint(ext, impl) {
|
||||
if (init) {
|
||||
throw new Error(
|
||||
'registerExtensionPoint called after registerInit',
|
||||
);
|
||||
}
|
||||
extensionPoints.push([ext, impl]);
|
||||
},
|
||||
registerInit(regInit) {
|
||||
if (init) {
|
||||
throw new Error('registerInit must only be called once');
|
||||
@@ -220,6 +231,7 @@ export function createBackendModule<TOptions extends [options?: object] = []>(
|
||||
type: 'module',
|
||||
pluginId: c.pluginId,
|
||||
moduleId: c.moduleId,
|
||||
extensionPoints,
|
||||
init,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -59,6 +59,10 @@ export interface BackendPluginRegistrationPoints {
|
||||
* @public
|
||||
*/
|
||||
export interface BackendModuleRegistrationPoints {
|
||||
registerExtensionPoint<TExtensionPoint>(
|
||||
ref: ExtensionPoint<TExtensionPoint>,
|
||||
impl: TExtensionPoint,
|
||||
): void;
|
||||
registerInit<Deps extends { [name in string]: unknown }>(options: {
|
||||
deps: {
|
||||
[name in keyof Deps]: ServiceRef<Deps[name]> | ExtensionPoint<Deps[name]>;
|
||||
@@ -105,6 +109,7 @@ export interface InternalBackendModuleRegistration {
|
||||
pluginId: string;
|
||||
moduleId: string;
|
||||
type: 'module';
|
||||
extensionPoints: Array<readonly [ExtensionPoint<unknown>, unknown]>;
|
||||
init: {
|
||||
deps: Record<string, ServiceRef<unknown> | ExtensionPoint<unknown>>;
|
||||
func(deps: Record<string, unknown>): Promise<void>;
|
||||
|
||||
Reference in New Issue
Block a user