diff --git a/.changeset/rich-bags-call.md b/.changeset/rich-bags-call.md new file mode 100644 index 0000000000..ef9691bf74 --- /dev/null +++ b/.changeset/rich-bags-call.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/backend-app-api': patch +'@backstage/plugin-app-backend': patch +--- + +Internal refactor to match new options pattern in the experimental backend system. diff --git a/.changeset/slow-pumas-tap.md b/.changeset/slow-pumas-tap.md new file mode 100644 index 0000000000..eabcb5fd94 --- /dev/null +++ b/.changeset/slow-pumas-tap.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +Updated all factory function creators to accept options as a top-level callback rather than extra parameter to the main factory function. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index b1356e93e3..199b0863de 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -46,14 +46,10 @@ export interface Backend { } // @public (undocumented) -export const cacheFactory: ( - options?: undefined, -) => ServiceFactory; +export const cacheFactory: () => ServiceFactory; // @public (undocumented) -export const configFactory: ( - options?: undefined, -) => ServiceFactory; +export const configFactory: () => ServiceFactory; // @public export function createHttpServer( @@ -76,9 +72,7 @@ export interface CreateSpecializedBackendOptions { } // @public (undocumented) -export const databaseFactory: ( - options?: undefined, -) => ServiceFactory; +export const databaseFactory: () => ServiceFactory; // @public export class DefaultRootHttpRouter implements RootHttpRouterService { @@ -96,9 +90,7 @@ export interface DefaultRootHttpRouterOptions { } // @public (undocumented) -export const discoveryFactory: ( - options?: undefined, -) => ServiceFactory; +export const discoveryFactory: () => ServiceFactory; // @public export interface ExtendedHttpServer extends http.Server { @@ -116,9 +108,9 @@ export const httpRouterFactory: ( ) => ServiceFactory; // @public (undocumented) -export type HttpRouterFactoryOptions = { +export interface HttpRouterFactoryOptions { getPath(pluginId: string): string; -}; +} // @public export type HttpServerCertificateOptions = @@ -144,9 +136,7 @@ export type HttpServerOptions = { }; // @public (undocumented) -export const identityFactory: ( - options?: IdentityFactoryOptions | undefined, -) => ServiceFactory; +export const identityFactory: () => ServiceFactory; // @public export type IdentityFactoryOptions = { @@ -155,14 +145,10 @@ export type IdentityFactoryOptions = { }; // @public -export const lifecycleFactory: ( - options?: undefined, -) => ServiceFactory; +export const lifecycleFactory: () => ServiceFactory; // @public (undocumented) -export const loggerFactory: ( - options?: undefined, -) => ServiceFactory; +export const loggerFactory: () => ServiceFactory; // @public export class MiddlewareFactory { @@ -190,9 +176,7 @@ export interface MiddlewareFactoryOptions { } // @public (undocumented) -export const permissionsFactory: ( - options?: undefined, -) => ServiceFactory; +export const permissionsFactory: () => ServiceFactory; // @public export function readCorsOptions(config?: Config): CorsOptions; @@ -220,9 +204,7 @@ export interface RootHttpRouterConfigureOptions { } // @public (undocumented) -export const rootHttpRouterFactory: ( - options?: RootHttpRouterFactoryOptions | undefined, -) => ServiceFactory; +export const rootHttpRouterFactory: () => ServiceFactory; // @public (undocumented) export type RootHttpRouterFactoryOptions = { @@ -231,19 +213,13 @@ export type RootHttpRouterFactoryOptions = { }; // @public -export const rootLifecycleFactory: ( - options?: undefined, -) => ServiceFactory; +export const rootLifecycleFactory: () => ServiceFactory; // @public (undocumented) -export const rootLoggerFactory: ( - options?: undefined, -) => ServiceFactory; +export const rootLoggerFactory: () => ServiceFactory; // @public (undocumented) -export const schedulerFactory: ( - options?: undefined, -) => ServiceFactory; +export const schedulerFactory: () => ServiceFactory; // @public (undocumented) export type ServiceOrExtensionPoint = @@ -251,12 +227,8 @@ export type ServiceOrExtensionPoint = | ServiceRef; // @public (undocumented) -export const tokenManagerFactory: ( - options?: undefined, -) => ServiceFactory; +export const tokenManagerFactory: () => ServiceFactory; // @public (undocumented) -export const urlReaderFactory: ( - options?: undefined, -) => ServiceFactory; +export const urlReaderFactory: () => ServiceFactory; ``` diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts index f1fc089ea3..8787b1ad9e 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts @@ -23,30 +23,32 @@ import { Handler } from 'express'; /** * @public */ -export type HttpRouterFactoryOptions = { +export interface HttpRouterFactoryOptions { /** * A callback used to generate the path for each plugin, defaults to `/api/{pluginId}`. */ getPath(pluginId: string): string; -}; +} /** @public */ -export const httpRouterFactory = createServiceFactory({ - service: coreServices.httpRouter, - deps: { - plugin: coreServices.pluginMetadata, - rootHttpRouter: coreServices.rootHttpRouter, - }, - async factory({ rootHttpRouter }, options?: HttpRouterFactoryOptions) { - const getPath = options?.getPath ?? (id => `/api/${id}`); +export const httpRouterFactory = createServiceFactory( + (options?: HttpRouterFactoryOptions) => ({ + service: coreServices.httpRouter, + deps: { + plugin: coreServices.pluginMetadata, + rootHttpRouter: coreServices.rootHttpRouter, + }, + async factory({ rootHttpRouter }) { + const getPath = options?.getPath ?? (id => `/api/${id}`); - return async ({ plugin }) => { - const path = getPath(plugin.getId()); - return { - use(handler: Handler) { - rootHttpRouter.use(path, handler); - }, + return async ({ plugin }) => { + const path = getPath(plugin.getId()); + return { + use(handler: Handler) { + rootHttpRouter.use(path, handler); + }, + }; }; - }; - }, -}); + }, + }), +); diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts index 9348f59d64..405a2fc630 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.test.ts @@ -143,7 +143,7 @@ describe('ServiceRegistry', () => { const factory = createServiceFactory({ service: ref1, deps: { rootDep: ref2 }, - async factory({ rootDep }) { + factory: async ({ rootDep }) => { return async () => ({ x: rootDep.x }); }, }); diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 213815f782..33190277c9 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -23,7 +23,7 @@ export interface BackendFeature { } // @public (undocumented) -export interface BackendModuleConfig { +export interface BackendModuleConfig { // (undocumented) moduleId: string; // (undocumented) @@ -31,16 +31,15 @@ export interface BackendModuleConfig { // (undocumented) register( reg: Omit, - options: TOptions, ): void; } // @public (undocumented) -export interface BackendPluginConfig { +export interface BackendPluginConfig { // (undocumented) id: string; // (undocumented) - register(reg: BackendRegistrationPoints, options: TOptions): void; + register(reg: BackendRegistrationPoints): void; } // @public (undocumented) @@ -113,14 +112,14 @@ export namespace coreServices { } // @public -export function createBackendModule( - config: BackendModuleConfig, -): FactoryFunctionWithOptions; +export function createBackendModule( + config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), +): (...params: TOptions) => BackendFeature; // @public (undocumented) -export function createBackendPlugin( - config: BackendPluginConfig, -): FactoryFunctionWithOptions; +export function createBackendPlugin( + config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), +): (...params: TOptions) => BackendFeature; // @public (undocumented) export function createExtensionPoint( @@ -135,10 +134,14 @@ export function createServiceFactory< TDeps extends { [name in string]: ServiceRef; }, - TOpts extends MaybeOptions = undefined, + TOpts extends [options?: object] = [], >( - config: ServiceFactoryConfig, -): FactoryFunctionWithOptions, TOpts>; + config: + | ServiceFactoryConfig + | (( + ...options: TOpts + ) => ServiceFactoryConfig), +): (...params: TOpts) => ServiceFactory; // @public export function createServiceRef( @@ -337,14 +340,12 @@ export interface ServiceFactoryConfig< TDeps extends { [name in string]: ServiceRef; }, - TOpts extends MaybeOptions = undefined, > { // (undocumented) deps: TDeps; // (undocumented) factory( deps: ServiceRefsToInstances, - options: TOpts, ): TScope extends 'root' ? Promise : Promise<(deps: ServiceRefsToInstances) => Promise>; diff --git a/packages/backend-plugin-api/src/services/system/types.test.ts b/packages/backend-plugin-api/src/services/system/types.test.ts index 0e02f38d3f..9cbc45151d 100644 --- a/packages/backend-plugin-api/src/services/system/types.test.ts +++ b/packages/backend-plugin-api/src/services/system/types.test.ts @@ -16,9 +16,12 @@ import { createServiceFactory, createServiceRef } from './types'; +const ref = createServiceRef({ id: 'x' }); +const rootDep = createServiceRef({ id: 'y', scope: 'root' }); +const pluginDep = createServiceRef({ id: 'z' }); + describe('createServiceFactory', () => { it('should create a meta factory with no options', () => { - const ref = createServiceRef({ id: 'x' }); const metaFactory = createServiceFactory({ service: ref, deps: {}, @@ -37,19 +40,19 @@ describe('createServiceFactory', () => { metaFactory({ x: 1 }); // @ts-expect-error metaFactory(null); + // @ts-expect-error metaFactory(undefined); metaFactory(); }); it('should create a meta factory with optional options', () => { - const ref = createServiceRef({ id: 'x' }); - const metaFactory = createServiceFactory({ + const metaFactory = createServiceFactory((_opts?: { x: number }) => ({ service: ref, deps: {}, - async factory(_deps, _opts?: { x: number }) { + async factory() { return async () => 'x'; }, - }); + })); expect(metaFactory).toEqual(expect.any(Function)); // @ts-expect-error @@ -66,14 +69,13 @@ describe('createServiceFactory', () => { }); it('should create a meta factory with required options', () => { - const ref = createServiceRef({ id: 'x' }); - const metaFactory = createServiceFactory({ + const metaFactory = createServiceFactory((_opts: { x: number }) => ({ service: ref, deps: {}, - async factory(_deps, _opts: { x: number }) { + async factory() { return async () => 'x'; }, - }); + })); expect(metaFactory).toEqual(expect.any(Function)); // @ts-expect-error @@ -95,14 +97,13 @@ describe('createServiceFactory', () => { interface TestOptions { x: number; } - const ref = createServiceRef({ id: 'x' }); - const metaFactory = createServiceFactory({ + const metaFactory = createServiceFactory((_opts?: TestOptions) => ({ service: ref, deps: {}, - async factory(_deps, _opts?: TestOptions) { + async factory() { return async () => 'x'; }, - }); + })); expect(metaFactory).toEqual(expect.any(Function)); // @ts-expect-error @@ -122,14 +123,13 @@ describe('createServiceFactory', () => { interface TestOptions { x: number; } - const ref = createServiceRef({ id: 'x' }); - const metaFactory = createServiceFactory({ + const metaFactory = createServiceFactory((_opts: TestOptions) => ({ service: ref, deps: {}, - async factory(_deps, _opts: TestOptions) { + async factory() { return async () => 'x'; }, - }); + })); expect(metaFactory).toEqual(expect.any(Function)); // @ts-expect-error @@ -147,80 +147,163 @@ describe('createServiceFactory', () => { metaFactory(); }); - it('should only allow objects as options', () => { - const ref = createServiceRef({ id: 'x' }); - const metaFactory = createServiceFactory({ + it('should create factory with required options and dependencies', () => { + interface TestOptions { + x: number; + } + + function unused(..._any: any[]) {} + + const metaFactory = createServiceFactory((_opts: TestOptions) => ({ service: ref, - deps: {}, - // @ts-expect-error - async factory(_deps, _opts: string) { - return async () => 'x'; + deps: { + root: rootDep, + plugin: pluginDep, }, - }); + async factory({ root }) { + const root1: number = root; + // @ts-expect-error + const root2: string = root; + return async ({ plugin }) => { + const plugin3: boolean = plugin; + // @ts-expect-error + const plugin4: number = plugin; + unused(root1, root2, plugin3, plugin4); + return 'x'; + }; + }, + })); expect(metaFactory).toEqual(expect.any(Function)); - createServiceFactory({ + + // @ts-expect-error + metaFactory('string'); + // @ts-expect-error + metaFactory({}); + metaFactory({ x: 1 }); + // @ts-expect-error + metaFactory({ x: 1, y: 2 }); + // @ts-expect-error + metaFactory(null); + // @ts-expect-error + metaFactory(undefined); + // @ts-expect-error + metaFactory(); + }); + + it('should create factory with optional options and dependencies', () => { + interface TestOptions { + x: number; + } + + function unused(..._any: any[]) {} + + const metaFactory = createServiceFactory((_opts?: TestOptions) => ({ + service: ref, + deps: { + root: rootDep, + plugin: pluginDep, + }, + async factory({ root }) { + const root1: number = root; + // @ts-expect-error + const root2: string = root; + return async ({ plugin }) => { + const plugin3: boolean = plugin; + // @ts-expect-error + const plugin4: number = plugin; + unused(root1, root2, plugin3, plugin4); + return 'x'; + }; + }, + })); + expect(metaFactory).toEqual(expect.any(Function)); + + // @ts-expect-error + metaFactory('string'); + // @ts-expect-error + metaFactory({}); + metaFactory({ x: 1 }); + // @ts-expect-error + metaFactory({ x: 1, y: 2 }); + // @ts-expect-error + metaFactory(null); + metaFactory(undefined); + metaFactory(); + }); + + it('should only allow objects as options', () => { + // @ts-expect-error + const metaFactory = createServiceFactory((_opts: string) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: number) { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + expect(metaFactory).toEqual(expect.any(Function)); + // @ts-expect-error + createServiceFactory((_opts: number) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: symbol) { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + // @ts-expect-error + createServiceFactory((_opts: symbol) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: bigint) { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + // @ts-expect-error + createServiceFactory((_opts: bigint) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: 'string') { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + // @ts-expect-error + createServiceFactory((_opts: 'string') => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: Array) { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + // @ts-expect-error + createServiceFactory((_opts: Array) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: Map) { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + // @ts-expect-error + createServiceFactory((_opts: Map) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: Set) { + async factory() { return async () => 'x'; }, - }); - createServiceFactory({ + })); + // @ts-expect-error + createServiceFactory((_opts: Set) => ({ service: ref, deps: {}, - // @ts-expect-error - async factory(_deps, _opts: null) { + async factory() { return async () => 'x'; }, - }); + })); + // @ts-expect-error + createServiceFactory((_opts: null) => ({ + service: ref, + deps: {}, + async factory() { + return async () => 'x'; + }, + })); }); }); diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index ffbbdb5f0c..34c0a50005 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { FactoryFunctionWithOptions, MaybeOptions } from '../../types'; - /** * TODO * @@ -133,9 +131,7 @@ type ServiceRefsToInstances< T extends { [key in string]: ServiceRef }, TScope extends 'root' | 'plugin' = 'root' | 'plugin', > = { - [name in { - [key in keyof T]: T[key] extends ServiceRef ? key : never; - }[keyof T]]: T[name] extends ServiceRef ? TImpl : never; + [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['T']; }; /** @public */ @@ -144,13 +140,11 @@ export interface ServiceFactoryConfig< TScope extends 'root' | 'plugin', TImpl extends TService, TDeps extends { [name in string]: ServiceRef }, - TOpts extends MaybeOptions = undefined, > { service: ServiceRef; deps: TDeps; factory( deps: ServiceRefsToInstances, - options: TOpts, ): TScope extends 'root' ? Promise : Promise<(deps: ServiceRefsToInstances) => Promise>; @@ -164,17 +158,23 @@ export function createServiceFactory< TScope extends 'root' | 'plugin', TImpl extends TService, TDeps extends { [name in string]: ServiceRef }, - TOpts extends MaybeOptions = undefined, + TOpts extends [options?: object] = [], >( - config: ServiceFactoryConfig, -): FactoryFunctionWithOptions, TOpts> { - return (options?: TOpts) => + config: + | ServiceFactoryConfig + | (( + ...options: TOpts + ) => ServiceFactoryConfig), +): (...params: TOpts) => ServiceFactory { + if (typeof config === 'function') { + return (...opts: TOpts) => { + const c = config(...opts); + return { ...c, scope: c.service.scope } as ServiceFactory; + }; + } + return () => ({ + ...config, scope: config.service.scope, - service: config.service, - deps: config.deps, - factory(deps: ServiceRefsToInstances) { - return config.factory(deps, options!); - }, } as ServiceFactory); } diff --git a/packages/backend-plugin-api/src/types.ts b/packages/backend-plugin-api/src/types.ts deleted file mode 100644 index 6da3bafe17..0000000000 --- a/packages/backend-plugin-api/src/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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. - */ - -/** - * Base type for options objects that aren't required. - * - * @ignore - */ -export type MaybeOptions = object | undefined; - -/** - * Helper type that makes the options argument optional if options are not required. - * - * @ignore - */ -export type FactoryFunctionWithOptions = - undefined extends TOptions - ? (options?: TOptions) => TResult - : (options: TOptions) => TResult; diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index cf67e411d5..dbdf0ead14 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -32,10 +32,10 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { - const plugin = createBackendPlugin({ + const plugin = createBackendPlugin((_options: { a: string }) => ({ id: 'x', - register(_reg, _options: { a: string }) {}, - }); + register() {}, + })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); expect(plugin({ a: 'a' }).id).toBe('x'); @@ -46,10 +46,10 @@ describe('createBackendPlugin', () => { }); it('should create plugins with optional options', () => { - const plugin = createBackendPlugin({ + const plugin = createBackendPlugin((_options?: { a: string }) => ({ id: 'x', - register(_reg, _options?: { a: string }) {}, - }); + register() {}, + })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); expect(plugin()).toBeDefined(); @@ -73,10 +73,10 @@ describe('createBackendPlugin', () => { interface TestOptions { a: string; } - const plugin = createBackendPlugin({ + const plugin = createBackendPlugin((_options: TestOptions) => ({ id: 'x', - register(_reg, _options: TestOptions) {}, - }); + register() {}, + })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); expect(plugin({ a: 'a' }).id).toBe('x'); @@ -90,10 +90,10 @@ describe('createBackendPlugin', () => { interface TestOptions { a: string; } - const plugin = createBackendPlugin({ + const plugin = createBackendPlugin((_options?: TestOptions) => ({ id: 'x', - register(_reg, _options?: TestOptions) {}, - }); + register() {}, + })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); expect(plugin()).toBeDefined(); @@ -104,11 +104,11 @@ describe('createBackendPlugin', () => { describe('createBackendModule', () => { it('should create a BackendModule', () => { - const mod = createBackendModule({ + const mod = createBackendModule((_options: { a: string }) => ({ pluginId: 'x', moduleId: 'y', - register(_reg, _options: { a: string }) {}, - }); + register() {}, + })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); expect(mod({ a: 'a' }).id).toBe('x.y'); @@ -119,11 +119,11 @@ describe('createBackendModule', () => { }); it('should create modules with optional options', () => { - const mod = createBackendModule({ + const mod = createBackendModule((_options?: { a: string }) => ({ pluginId: 'x', moduleId: 'y', - register(_reg, _options?: { a: string }) {}, - }); + register() {}, + })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); expect(mod()).toBeDefined(); @@ -148,11 +148,11 @@ describe('createBackendModule', () => { interface TestOptions { a: string; } - const mod = createBackendModule({ + const mod = createBackendModule((_options: TestOptions) => ({ pluginId: 'x', moduleId: 'y', - register(_reg, _options: TestOptions) {}, - }); + register() {}, + })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); expect(mod({ a: 'a' }).id).toBe('x.y'); @@ -166,11 +166,11 @@ describe('createBackendModule', () => { interface TestOptions { a: string; } - const mod = createBackendModule({ + const mod = createBackendModule((_options?: TestOptions) => ({ pluginId: 'x', moduleId: 'y', - register(_reg, _options?: TestOptions) {}, - }); + register() {}, + })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); expect(mod()).toBeDefined(); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index 4c384840cd..31a64778f2 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { FactoryFunctionWithOptions, MaybeOptions } from '../types'; import { BackendRegistrationPoints, BackendFeature, @@ -43,30 +42,28 @@ export function createExtensionPoint( } /** @public */ -export interface BackendPluginConfig { +export interface BackendPluginConfig { id: string; - register(reg: BackendRegistrationPoints, options: TOptions): void; + register(reg: BackendRegistrationPoints): void; } /** @public */ -export function createBackendPlugin( - config: BackendPluginConfig, -): FactoryFunctionWithOptions { - return (options?: TOptions) => ({ - id: config.id, - register(register: BackendRegistrationPoints) { - return config.register(register, options!); - }, - }); +export function createBackendPlugin( + config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), +): (...params: TOptions) => BackendFeature { + if (typeof config === 'function') { + return config; + } + + return () => config; } /** @public */ -export interface BackendModuleConfig { +export interface BackendModuleConfig { pluginId: string; moduleId: string; register( reg: Omit, - options: TOptions, ): void; } @@ -84,14 +81,23 @@ export interface BackendModuleConfig { * * The `pluginId` should exactly match the `id` of the plugin that the module extends. */ -export function createBackendModule( - config: BackendModuleConfig, -): FactoryFunctionWithOptions { - return (options?: TOptions) => ({ +export function createBackendModule( + config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), +): (...params: TOptions) => BackendFeature { + if (typeof config === 'function') { + return (...options: TOptions) => { + const c = config(...options); + return { + id: `${c.pluginId}.${c.moduleId}`, + register: c.register, + }; + }; + } + return () => ({ id: `${config.pluginId}.${config.moduleId}`, register(register: BackendRegistrationPoints) { // TODO: Hide registerExtensionPoint - return config.register(register, options!); + return config.register(register); }, }); } diff --git a/packages/backend-test-utils/src/next/implementations/mockConfigService.ts b/packages/backend-test-utils/src/next/implementations/mockConfigService.ts index 78a670585d..a5578b866f 100644 --- a/packages/backend-test-utils/src/next/implementations/mockConfigService.ts +++ b/packages/backend-test-utils/src/next/implementations/mockConfigService.ts @@ -22,10 +22,12 @@ import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; /** @public */ -export const mockConfigFactory = createServiceFactory({ - service: coreServices.config, - deps: {}, - async factory(_, options?: { data?: JsonObject }) { - return new ConfigReader(options?.data, 'mock-config'); - }, -}); +export const mockConfigFactory = createServiceFactory( + (options?: { data?: JsonObject }) => ({ + service: coreServices.config, + deps: {}, + async factory() { + return new ConfigReader(options?.data, 'mock-config'); + }, + }), +); diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts index 2c0c73c71b..b12a8d6877 100644 --- a/plugins/app-backend/src/service/appPlugin.ts +++ b/plugins/app-backend/src/service/appPlugin.ts @@ -70,9 +70,9 @@ export type AppPluginOptions = { * The App plugin is responsible for serving the frontend app bundle and static assets. * @alpha */ -export const appPlugin = createBackendPlugin({ +export const appPlugin = createBackendPlugin((options: AppPluginOptions) => ({ id: 'app', - register(env, options: AppPluginOptions) { + register(env) { env.registerInit({ deps: { logger: coreServices.logger, @@ -101,4 +101,4 @@ export const appPlugin = createBackendPlugin({ }, }); }, -}); +})); diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md index a911fb5ebb..63b85f223b 100644 --- a/plugins/catalog-backend-module-aws/api-report.md +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -90,7 +90,5 @@ export class AwsS3EntityProvider implements EntityProvider { } // @alpha -export const awsS3EntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const awsS3EntityProviderCatalogModule: () => BackendFeature; ``` diff --git a/plugins/catalog-backend-module-azure/api-report.md b/plugins/catalog-backend-module-azure/api-report.md index 84ffaf39e9..5ffae14b6b 100644 --- a/plugins/catalog-backend-module-azure/api-report.md +++ b/plugins/catalog-backend-module-azure/api-report.md @@ -58,7 +58,5 @@ export class AzureDevOpsEntityProvider implements EntityProvider { } // @alpha -export const azureDevOpsEntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const azureDevOpsEntityProviderCatalogModule: () => BackendFeature; ``` diff --git a/plugins/catalog-backend-module-bitbucket-cloud/api-report.md b/plugins/catalog-backend-module-bitbucket-cloud/api-report.md index 480395e477..7ad6b3b3e0 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/api-report.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/api-report.md @@ -48,7 +48,5 @@ export class BitbucketCloudEntityProvider } // @alpha (undocumented) -export const bitbucketCloudEntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const bitbucketCloudEntityProviderCatalogModule: () => BackendFeature; ``` diff --git a/plugins/catalog-backend-module-bitbucket-server/api-report.md b/plugins/catalog-backend-module-bitbucket-server/api-report.md index a38a4d8c35..213f5d2573 100644 --- a/plugins/catalog-backend-module-bitbucket-server/api-report.md +++ b/plugins/catalog-backend-module-bitbucket-server/api-report.md @@ -69,9 +69,7 @@ export class BitbucketServerEntityProvider implements EntityProvider { } // @alpha (undocumented) -export const bitbucketServerEntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const bitbucketServerEntityProviderCatalogModule: () => BackendFeature; // @public (undocumented) export type BitbucketServerListOptions = { diff --git a/plugins/catalog-backend-module-gerrit/api-report.md b/plugins/catalog-backend-module-gerrit/api-report.md index 45847ea93d..870937f7ec 100644 --- a/plugins/catalog-backend-module-gerrit/api-report.md +++ b/plugins/catalog-backend-module-gerrit/api-report.md @@ -31,9 +31,7 @@ export class GerritEntityProvider implements EntityProvider { } // @alpha (undocumented) -export const gerritEntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const gerritEntityProviderCatalogModule: () => BackendFeature; // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index 78ffd5b018..a66ec712c7 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -101,9 +101,7 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { } // @alpha -export const githubEntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const githubEntityProviderCatalogModule: () => BackendFeature; // @public (undocumented) export class GithubLocationAnalyzer implements ScmLocationAnalyzer { diff --git a/plugins/catalog-backend-module-gitlab/api-report.md b/plugins/catalog-backend-module-gitlab/api-report.md index 9ed90a2c42..36713d2427 100644 --- a/plugins/catalog-backend-module-gitlab/api-report.md +++ b/plugins/catalog-backend-module-gitlab/api-report.md @@ -34,9 +34,7 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { } // @alpha -export const gitlabDiscoveryEntityProviderCatalogModule: ( - options?: undefined, -) => BackendFeature; +export const gitlabDiscoveryEntityProviderCatalogModule: () => BackendFeature; // @public export class GitLabDiscoveryProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts index 0ecb45292c..b173b2d2ef 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts @@ -31,51 +31,50 @@ import { WrapperProviders } from './WrapperProviders'; * @alpha */ export const incrementalIngestionEntityProviderCatalogModule = - createBackendModule({ - pluginId: 'catalog', - moduleId: 'incrementalIngestionEntityProvider', - register( - env, - options: { - providers: Array<{ - provider: IncrementalEntityProvider; - options: IncrementalEntityProviderOptions; - }>; - }, - ) { - env.registerInit({ - deps: { - catalog: catalogProcessingExtensionPoint, - config: coreServices.config, - database: coreServices.database, - httpRouter: coreServices.httpRouter, - logger: coreServices.logger, - scheduler: coreServices.scheduler, - }, - async init({ - catalog, - config, - database, - httpRouter, - logger, - scheduler, - }) { - const client = await database.getClient(); - - const providers = new WrapperProviders({ + createBackendModule( + (options: { + providers: Array<{ + provider: IncrementalEntityProvider; + options: IncrementalEntityProviderOptions; + }>; + }) => ({ + pluginId: 'catalog', + moduleId: 'incrementalIngestionEntityProvider', + register(env) { + env.registerInit({ + deps: { + catalog: catalogProcessingExtensionPoint, + config: coreServices.config, + database: coreServices.database, + httpRouter: coreServices.httpRouter, + logger: coreServices.logger, + scheduler: coreServices.scheduler, + }, + async init({ + catalog, config, + database, + httpRouter, logger, - client, scheduler, - }); + }) { + const client = await database.getClient(); - for (const entry of options.providers) { - const wrapped = providers.wrap(entry.provider, entry.options); - catalog.addEntityProvider(wrapped); - } + const providers = new WrapperProviders({ + config, + logger, + client, + scheduler, + }); - httpRouter.use(await providers.adminRouter()); - }, - }); - }, - }); + for (const entry of options.providers) { + const wrapped = providers.wrap(entry.provider, entry.options); + catalog.addEntityProvider(wrapped); + } + + httpRouter.use(await providers.adminRouter()); + }, + }); + }, + }), + ); diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index 921d682b89..a5abdc17c6 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -135,9 +135,7 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider { } // @alpha -export const microsoftGraphOrgEntityProviderCatalogModule: ( - options?: MicrosoftGraphOrgEntityProviderCatalogModuleOptions | undefined, -) => BackendFeature; +export const microsoftGraphOrgEntityProviderCatalogModule: () => BackendFeature; // @alpha export interface MicrosoftGraphOrgEntityProviderCatalogModuleOptions { diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 3e6c5ef676..6ff9ac4b1f 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -237,7 +237,7 @@ export type CatalogPermissionRule< > = PermissionRule; // @alpha -export const catalogPlugin: (options?: undefined) => BackendFeature; +export const catalogPlugin: () => BackendFeature; // @public export interface CatalogProcessingEngine { diff --git a/plugins/events-backend-module-aws-sqs/api-report.md b/plugins/events-backend-module-aws-sqs/api-report.md index 79a422c9f3..ede18f2787 100644 --- a/plugins/events-backend-module-aws-sqs/api-report.md +++ b/plugins/events-backend-module-aws-sqs/api-report.md @@ -23,7 +23,5 @@ export class AwsSqsConsumingEventPublisher implements EventPublisher { } // @alpha -export const awsSqsConsumingEventPublisherEventsModule: ( - options?: undefined, -) => BackendFeature; +export const awsSqsConsumingEventPublisherEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-azure/api-report.md b/plugins/events-backend-module-azure/api-report.md index 510ec91c47..2e13a7ed4a 100644 --- a/plugins/events-backend-module-azure/api-report.md +++ b/plugins/events-backend-module-azure/api-report.md @@ -15,7 +15,5 @@ export class AzureDevOpsEventRouter extends SubTopicEventRouter { } // @alpha -export const azureDevOpsEventRouterEventsModule: ( - options?: undefined, -) => BackendFeature; +export const azureDevOpsEventRouterEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-bitbucket-cloud/api-report.md b/plugins/events-backend-module-bitbucket-cloud/api-report.md index 0e4acfac91..c47252ce17 100644 --- a/plugins/events-backend-module-bitbucket-cloud/api-report.md +++ b/plugins/events-backend-module-bitbucket-cloud/api-report.md @@ -15,7 +15,5 @@ export class BitbucketCloudEventRouter extends SubTopicEventRouter { } // @alpha -export const bitbucketCloudEventRouterEventsModule: ( - options?: undefined, -) => BackendFeature; +export const bitbucketCloudEventRouterEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-gerrit/api-report.md b/plugins/events-backend-module-gerrit/api-report.md index 268e5970fa..c8d4a7c9b6 100644 --- a/plugins/events-backend-module-gerrit/api-report.md +++ b/plugins/events-backend-module-gerrit/api-report.md @@ -15,7 +15,5 @@ export class GerritEventRouter extends SubTopicEventRouter { } // @alpha -export const gerritEventRouterEventsModule: ( - options?: undefined, -) => BackendFeature; +export const gerritEventRouterEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-github/api-report.md b/plugins/events-backend-module-github/api-report.md index b2a4425ae6..4f14bce789 100644 --- a/plugins/events-backend-module-github/api-report.md +++ b/plugins/events-backend-module-github/api-report.md @@ -22,10 +22,8 @@ export class GithubEventRouter extends SubTopicEventRouter { } // @alpha -export const githubEventRouterEventsModule: ( - options?: undefined, -) => BackendFeature; +export const githubEventRouterEventsModule: () => BackendFeature; // @alpha -export const githubWebhookEventsModule: (options?: undefined) => BackendFeature; +export const githubWebhookEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-gitlab/api-report.md b/plugins/events-backend-module-gitlab/api-report.md index 8f130902a2..2a88295032 100644 --- a/plugins/events-backend-module-gitlab/api-report.md +++ b/plugins/events-backend-module-gitlab/api-report.md @@ -20,10 +20,8 @@ export class GitlabEventRouter extends SubTopicEventRouter { } // @alpha -export const gitlabEventRouterEventsModule: ( - options?: undefined, -) => BackendFeature; +export const gitlabEventRouterEventsModule: () => BackendFeature; // @alpha -export const gitlabWebhookEventsModule: (options?: undefined) => BackendFeature; +export const gitlabWebhookEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend/api-report.md b/plugins/events-backend/api-report.md index 69d7600ed3..28437772ae 100644 --- a/plugins/events-backend/api-report.md +++ b/plugins/events-backend/api-report.md @@ -29,7 +29,7 @@ export class EventsBackend { } // @alpha -export const eventsPlugin: (options?: undefined) => BackendFeature; +export const eventsPlugin: () => BackendFeature; // @public export class HttpPostIngressEventPublisher implements EventPublisher { diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index c89ead6d2b..21026c203c 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -625,7 +625,7 @@ export type RunCommandOptions = { }; // @alpha -export const scaffolderCatalogModule: (options?: undefined) => BackendFeature; +export const scaffolderCatalogModule: () => BackendFeature; // @public (undocumented) export class ScaffolderEntitiesProcessor implements CatalogProcessor { diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 5d4c16e2dc..71472abda6 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -70,72 +70,74 @@ export const scaffolderActionsExtensionPoint = * Catalog plugin * @alpha */ -export const scaffolderPlugin = createBackendPlugin({ - id: 'scaffolder', - register(env, options: ScaffolderPluginOptions) { - const actionsExtensions = new ScaffolderActionsExtensionPointImpl(); - env.registerExtensionPoint( - scaffolderActionsExtensionPoint, - actionsExtensions, - ); +export const scaffolderPlugin = createBackendPlugin( + (options: ScaffolderPluginOptions) => ({ + id: 'scaffolder', + register(env) { + const actionsExtensions = new ScaffolderActionsExtensionPointImpl(); + env.registerExtensionPoint( + scaffolderActionsExtensionPoint, + actionsExtensions, + ); - env.registerInit({ - deps: { - logger: coreServices.logger, - config: coreServices.config, - reader: coreServices.urlReader, - permissions: coreServices.permissions, - database: coreServices.database, - httpRouter: coreServices.httpRouter, - catalogClient: catalogServiceRef, - }, - async init({ - logger, - config, - reader, - database, - httpRouter, - catalogClient, - }) { - const { - additionalTemplateFilters, - taskBroker, - taskWorkers, - additionalTemplateGlobals, - } = options; - const log = loggerToWinstonLogger(logger); + env.registerInit({ + deps: { + logger: coreServices.logger, + config: coreServices.config, + reader: coreServices.urlReader, + permissions: coreServices.permissions, + database: coreServices.database, + httpRouter: coreServices.httpRouter, + catalogClient: catalogServiceRef, + }, + async init({ + logger, + config, + reader, + database, + httpRouter, + catalogClient, + }) { + const { + additionalTemplateFilters, + taskBroker, + taskWorkers, + additionalTemplateGlobals, + } = options; + const log = loggerToWinstonLogger(logger); - const actions = options.actions || [ - ...actionsExtensions.actions, - ...createBuiltinActions({ - integrations: ScmIntegrations.fromConfig(config), + const actions = options.actions || [ + ...actionsExtensions.actions, + ...createBuiltinActions({ + integrations: ScmIntegrations.fromConfig(config), + catalogClient, + reader, + config, + additionalTemplateFilters, + additionalTemplateGlobals, + }), + ]; + + const actionIds = actions.map(action => action.id).join(', '); + log.info( + `Starting scaffolder with the following actions enabled ${actionIds}`, + ); + + const router = await createRouter({ + logger: log, + config, + database, catalogClient, reader, - config, + actions, + taskBroker, + taskWorkers, additionalTemplateFilters, additionalTemplateGlobals, - }), - ]; - - const actionIds = actions.map(action => action.id).join(', '); - log.info( - `Starting scaffolder with the following actions enabled ${actionIds}`, - ); - - const router = await createRouter({ - logger: log, - config, - database, - catalogClient, - reader, - actions, - taskBroker, - taskWorkers, - additionalTemplateFilters, - additionalTemplateGlobals, - }); - httpRouter.use(router); - }, - }); - }, -}); + }); + httpRouter.use(router); + }, + }); + }, + }), +);