backend-plugin-api: remove plugin and module options

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-08-15 10:40:11 +02:00
parent ccc1a8d52a
commit 51987dbdaf
5 changed files with 37 additions and 174 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-plugin-api': minor
---
**BREAKING**: Removed the ability to define options for plugins and modules. Existing options should be migrated to instead use either static configuration or extension points.
+6 -6
View File
@@ -119,14 +119,14 @@ export namespace coreServices {
}
// @public
export function createBackendModule<TOptions extends [options?: object] = []>(
config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig),
): (...params: TOptions) => BackendFeature;
export function createBackendModule(
config: BackendModuleConfig,
): () => BackendFeature;
// @public
export function createBackendPlugin<TOptions extends [options?: object] = []>(
config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig),
): (...params: TOptions) => BackendFeature;
export function createBackendPlugin(
config: BackendPluginConfig,
): () => BackendFeature;
// @public
export function createExtensionPoint<T>(
@@ -33,22 +33,19 @@ describe('createExtensionPoint', () => {
describe('createBackendPlugin', () => {
it('should create a BackendPlugin', () => {
const plugin = createBackendPlugin((_options: { a: string }) => ({
const plugin = createBackendPlugin({
pluginId: 'x',
register(r) {
r.registerInit({ deps: {}, async init() {} });
},
}));
});
expect(plugin).toBeDefined();
expect(plugin({ a: 'a' })).toBeDefined();
expect(plugin({ a: 'a' })).toEqual({
expect(plugin()).toEqual({
$$type: '@backstage/BackendFeature',
version: 'v1',
getRegistrations: expect.any(Function),
});
expect(
(plugin({ a: 'a' }) as InternalBackendFeature).getRegistrations(),
).toEqual([
expect((plugin() as InternalBackendFeature).getRegistrations()).toEqual([
{
type: 'plugin',
pluginId: 'x',
@@ -60,91 +57,27 @@ describe('createBackendPlugin', () => {
},
]);
// @ts-expect-error
expect(plugin()).toBeDefined();
// @ts-expect-error
expect(plugin({ b: 'b' })).toBeDefined();
});
it('should create plugins with optional options', () => {
const plugin = createBackendPlugin((_options?: { a: string }) => ({
pluginId: 'x',
register() {},
}));
expect(plugin).toBeDefined();
expect(plugin({ a: 'a' })).toBeDefined();
expect(plugin()).toBeDefined();
// @ts-expect-error
expect(plugin({ b: 'b' })).toBeDefined();
});
it('should create plugins without options', () => {
const plugin = createBackendPlugin({
pluginId: 'x',
register() {},
});
expect(plugin).toBeDefined();
// @ts-expect-error
expect(plugin({ a: 'a' })).toBeDefined();
// @ts-expect-error
expect(plugin({})).toBeDefined();
});
it('should create a BackendPlugin with options as interface', () => {
interface TestOptions {
a: string;
}
const plugin = createBackendPlugin((_options: TestOptions) => ({
pluginId: 'x',
register() {},
}));
expect(plugin).toBeDefined();
expect(plugin({ a: 'a' })).toBeDefined();
expect(plugin({ a: 'a' })).toEqual({
$$type: '@backstage/BackendFeature',
version: 'v1',
getRegistrations: expect.any(Function),
});
// @ts-expect-error
expect(plugin()).toBeDefined();
// @ts-expect-error
expect(plugin({ b: 'b' })).toBeDefined();
});
it('should create plugins with optional options as interface', () => {
interface TestOptions {
a: string;
}
const plugin = createBackendPlugin((_options?: TestOptions) => ({
pluginId: 'x',
register() {},
}));
expect(plugin).toBeDefined();
expect(plugin({ a: 'a' })).toBeDefined();
expect(plugin()).toBeDefined();
// @ts-expect-error
expect(plugin({ b: 'b' })).toBeDefined();
});
});
describe('createBackendModule', () => {
it('should create a BackendModule', () => {
const mod = createBackendModule((_options: { a: string }) => ({
const mod = createBackendModule({
pluginId: 'x',
moduleId: 'y',
register(r) {
r.registerInit({ deps: {}, async init() {} });
},
}));
});
expect(mod).toBeDefined();
expect(mod({ a: 'a' })).toBeDefined();
expect(mod({ a: 'a' })).toEqual({
expect(mod()).toBeDefined();
expect(mod()).toEqual({
$$type: '@backstage/BackendFeature',
version: 'v1',
getRegistrations: expect.any(Function),
});
expect(
(mod({ a: 'a' }) as InternalBackendFeature).getRegistrations(),
).toEqual([
expect((mod() as InternalBackendFeature).getRegistrations()).toEqual([
{
type: 'module',
pluginId: 'x',
@@ -157,72 +90,6 @@ describe('createBackendModule', () => {
},
]);
// @ts-expect-error
expect(mod()).toBeDefined();
// @ts-expect-error
expect(mod({ b: 'b' })).toBeDefined();
});
it('should create modules with optional options', () => {
const mod = createBackendModule((_options?: { a: string }) => ({
pluginId: 'x',
moduleId: 'y',
register() {},
}));
expect(mod).toBeDefined();
expect(mod({ a: 'a' })).toBeDefined();
expect(mod()).toBeDefined();
// @ts-expect-error
expect(mod({ b: 'b' })).toBeDefined();
});
it('should create modules without options', () => {
const mod = createBackendModule({
pluginId: 'x',
moduleId: 'y',
register() {},
});
expect(mod).toBeDefined();
// @ts-expect-error
expect(mod({ a: 'a' })).toBeDefined();
// @ts-expect-error
expect(mod({})).toBeDefined();
});
it('should create a BackendModule as interface', () => {
interface TestOptions {
a: string;
}
const mod = createBackendModule((_options: TestOptions) => ({
pluginId: 'x',
moduleId: 'y',
register() {},
}));
expect(mod).toBeDefined();
expect(mod({ a: 'a' })).toBeDefined();
expect(mod({ a: 'a' })).toEqual({
$$type: '@backstage/BackendFeature',
version: 'v1',
getRegistrations: expect.any(Function),
});
// @ts-expect-error
expect(mod()).toBeDefined();
// @ts-expect-error
expect(mod({ b: 'b' })).toBeDefined();
});
it('should create modules with optional options as interface', () => {
interface TestOptions {
a: string;
}
const mod = createBackendModule((_options?: TestOptions) => ({
pluginId: 'x',
moduleId: 'y',
register() {},
}));
expect(mod).toBeDefined();
expect(mod({ a: 'a' })).toBeDefined();
expect(mod()).toBeDefined();
// @ts-expect-error
expect(mod({ b: 'b' })).toBeDefined();
});
});
@@ -85,14 +85,10 @@ export interface BackendPluginConfig {
* @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}
* @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
*/
export function createBackendPlugin<TOptions extends [options?: object] = []>(
config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig),
): (...params: TOptions) => BackendFeature {
const configCallback = typeof config === 'function' ? config : () => config;
const factory: BackendFeatureFactory<TOptions> = (...options) => {
const c = configCallback(...options);
export function createBackendPlugin(
config: BackendPluginConfig,
): () => BackendFeature {
const factory: BackendFeatureFactory = () => {
let registrations: InternalBackendPluginRegistration[];
return {
@@ -107,7 +103,7 @@ export function createBackendPlugin<TOptions extends [options?: object] = []>(
let init: InternalBackendPluginRegistration['init'] | undefined =
undefined;
c.register({
config.register({
registerExtensionPoint(ext, impl) {
if (init) {
throw new Error(
@@ -129,14 +125,14 @@ export function createBackendPlugin<TOptions extends [options?: object] = []>(
if (!init) {
throw new Error(
`registerInit was not called by register in ${c.pluginId}`,
`registerInit was not called by register in ${config.pluginId}`,
);
}
registrations = [
{
type: 'plugin',
pluginId: c.pluginId,
pluginId: config.pluginId,
extensionPoints,
init,
},
@@ -179,13 +175,10 @@ export interface BackendModuleConfig {
* @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}
* @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
*/
export function createBackendModule<TOptions extends [options?: object] = []>(
config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig),
): (...params: TOptions) => BackendFeature {
const configCallback = typeof config === 'function' ? config : () => config;
const factory: BackendFeatureFactory<TOptions> = (...options: TOptions) => {
const c = configCallback(...options);
export function createBackendModule(
config: BackendModuleConfig,
): () => BackendFeature {
const factory: BackendFeatureFactory = () => {
let registrations: InternalBackendModuleRegistration[];
return {
@@ -200,7 +193,7 @@ export function createBackendModule<TOptions extends [options?: object] = []>(
let init: InternalBackendModuleRegistration['init'] | undefined =
undefined;
c.register({
config.register({
registerExtensionPoint(ext, impl) {
if (init) {
throw new Error(
@@ -222,15 +215,15 @@ export function createBackendModule<TOptions extends [options?: object] = []>(
if (!init) {
throw new Error(
`registerInit was not called by register in ${c.moduleId} module for ${c.pluginId}`,
`registerInit was not called by register in ${config.moduleId} module for ${config.pluginId}`,
);
}
registrations = [
{
type: 'module',
pluginId: c.pluginId,
moduleId: c.moduleId,
pluginId: config.pluginId,
moduleId: config.moduleId,
extensionPoints,
init,
},
@@ -72,10 +72,8 @@ export interface BackendModuleRegistrationPoints {
}
/** @internal */
export interface BackendFeatureFactory<
TOptions extends [options?: object] = [],
> {
(...options: TOptions): BackendFeature;
export interface BackendFeatureFactory {
(): BackendFeature;
$$type: '@backstage/BackendFeatureFactory';
}