diff --git a/.changeset/friendly-days-march.md b/.changeset/friendly-days-march.md new file mode 100644 index 0000000000..a190c50a43 --- /dev/null +++ b/.changeset/friendly-days-march.md @@ -0,0 +1,7 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added `createFrontendModule` as a replacement for `createExtensionOverrides`, which is now deprecated. + +Deprecated the `BackstagePlugin` and `FrontendFeature` type in favor of `FrontendPlugin` and `FrontendFeature` from `@backstage/frontend-app-api` respectively. diff --git a/.changeset/friendly-months-march.md b/.changeset/friendly-months-march.md new file mode 100644 index 0000000000..0bb9cd7cf0 --- /dev/null +++ b/.changeset/friendly-months-march.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-app-api': patch +'@backstage/core-compat-api': patch +--- + +Added support for new `FrontendPlugin` and `FrontendModule` types. diff --git a/packages/app-next-example-plugin/api-report.md b/packages/app-next-example-plugin/api-report.md index fe2afb81a7..06d325b844 100644 --- a/packages/app-next-example-plugin/api-report.md +++ b/packages/app-next-example-plugin/api-report.md @@ -4,14 +4,14 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @public (undocumented) -const examplePlugin: BackstagePlugin< +const examplePlugin: FrontendPlugin< {}, {}, { diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md index 9e72d6178c..e61ee451d9 100644 --- a/packages/core-compat-api/api-report.md +++ b/packages/core-compat-api/api-report.md @@ -12,9 +12,10 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { BackstagePlugin as BackstagePlugin_2 } from '@backstage/frontend-plugin-api'; import { ComponentType } from 'react'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { ExtensionOverrides } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { ExternalRouteRef as ExternalRouteRef_2 } from '@backstage/frontend-plugin-api'; -import { FrontendFeature } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -28,7 +29,7 @@ export function compatWrapper(element: ReactNode): React_2.JSX.Element; // @public (undocumented) export function convertLegacyApp( rootElement: React_2.JSX.Element, -): FrontendFeature[]; +): (FrontendPlugin | ExtensionOverrides)[]; // @public (undocumented) export function convertLegacyPageExtension( diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx index b7b9f6781e..34d2937425 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -31,7 +31,7 @@ import { Navigate, Route, Routes } from 'react-router-dom'; import { collectLegacyRoutes } from './collectLegacyRoutes'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toInternalBackstagePlugin } from '../../frontend-plugin-api/src/wiring/createFrontendPlugin'; +import { toInternalFrontendPlugin } from '../../frontend-plugin-api/src/wiring/createFrontendPlugin'; import { createPlugin, createRoutableExtension, @@ -55,7 +55,7 @@ describe('collectLegacyRoutes', () => { expect( collected.map(p => ({ id: p.id, - extensions: toInternalBackstagePlugin(p).extensions.map(e => ({ + extensions: toInternalFrontendPlugin(p).extensions.map(e => ({ id: e.id, attachTo: e.attachTo, disabled: e.disabled, @@ -158,7 +158,7 @@ describe('collectLegacyRoutes', () => { expect( collected.map(p => ({ id: p.id, - extensions: toInternalBackstagePlugin(p).extensions.map(e => ({ + extensions: toInternalFrontendPlugin(p).extensions.map(e => ({ id: e.id, attachTo: e.attachTo, disabled: e.disabled, diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index 4c0e7efceb..197c245278 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -268,7 +268,10 @@ export function collectLegacyRoutes( extensions: [ ...extensions, ...Array.from(plugin.getApis()).map(factory => - ApiBlueprint.make({ namespace: factory.api.id, params: { factory } }), + ApiBlueprint.make({ + namespace: factory.api.id, + params: { factory }, + }), ), ], routes: convertLegacyRouteRefs(plugin.routes ?? {}), diff --git a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx index 445f42124f..0f9ccfb2ad 100644 --- a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx +++ b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx @@ -22,7 +22,7 @@ import { AppContextProvider } from '../../../core-app-api/src/app/AppContext'; import { RouteResolver } from '../../../core-plugin-api/src/routing/useRouteRef'; import { createFrontendPlugin as createNewPlugin, - BackstagePlugin as NewBackstagePlugin, + FrontendPlugin as NewFrontendPlugin, appTreeApiRef, componentsApiRef, coreComponentRefs, @@ -47,11 +47,11 @@ import { convertLegacyRouteRef } from '../convertLegacyRouteRef'; // Make sure that we only convert each new plugin instance to its legacy equivalent once const legacyPluginStore = getOrCreateGlobalSingleton( 'legacy-plugin-compatibility-store', - () => new WeakMap(), + () => new WeakMap(), ); export function toLegacyPlugin( - plugin: NewBackstagePlugin, + plugin: NewFrontendPlugin, ): LegacyBackstagePlugin { let legacy = legacyPluginStore.get(plugin); if (legacy) { @@ -83,7 +83,7 @@ export function toLegacyPlugin( } // TODO: Currently a very naive implementation, may need some more work -function toNewPlugin(plugin: LegacyBackstagePlugin): NewBackstagePlugin { +function toNewPlugin(plugin: LegacyBackstagePlugin): NewFrontendPlugin { return createNewPlugin({ id: plugin.getId(), }); diff --git a/packages/core-compat-api/src/convertLegacyApp.ts b/packages/core-compat-api/src/convertLegacyApp.ts index ffeab3bdc6..2729664941 100644 --- a/packages/core-compat-api/src/convertLegacyApp.ts +++ b/packages/core-compat-api/src/convertLegacyApp.ts @@ -22,7 +22,8 @@ import React, { isValidElement, } from 'react'; import { - FrontendFeature, + ExtensionOverrides, + FrontendPlugin, coreExtensionData, createExtension, createExtensionInput, @@ -60,7 +61,7 @@ function selectChildren( /** @public */ export function convertLegacyApp( rootElement: React.JSX.Element, -): FrontendFeature[] { +): (FrontendPlugin | ExtensionOverrides)[] { if (getComponentData(rootElement, 'core.type') === 'FlatRoutes') { return collectLegacyRoutes(rootElement); } diff --git a/packages/core-compat-api/src/convertLegacyPlugin.test.tsx b/packages/core-compat-api/src/convertLegacyPlugin.test.tsx index 657ee91725..3d5b001c61 100644 --- a/packages/core-compat-api/src/convertLegacyPlugin.test.tsx +++ b/packages/core-compat-api/src/convertLegacyPlugin.test.tsx @@ -24,7 +24,7 @@ import { import { convertLegacyPlugin } from './convertLegacyPlugin'; import { PageBlueprint } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toInternalBackstagePlugin } from '../../frontend-plugin-api/src/wiring/createFrontendPlugin'; +import { toInternalFrontendPlugin } from '../../frontend-plugin-api/src/wiring/createFrontendPlugin'; describe('convertLegacyPlugin', () => { it('should convert a plain legacy plugin to a new plugin', () => { @@ -34,7 +34,7 @@ describe('convertLegacyPlugin', () => { }), ).toMatchInlineSnapshot(` { - "$$type": "@backstage/BackstagePlugin", + "$$type": "@backstage/FrontendPlugin", "extensions": [], "externalRoutes": {}, "featureFlags": [], @@ -73,7 +73,7 @@ describe('convertLegacyPlugin', () => { }, ); - const internalConverted = toInternalBackstagePlugin(converted); + const internalConverted = toInternalFrontendPlugin(converted); expect(internalConverted.id).toBe('test'); expect(internalConverted.routes).toEqual({ diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index c837ff09b7..e8fa7572b7 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -5,7 +5,8 @@ ```ts import { ConfigApi } from '@backstage/core-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; -import { FrontendFeature } from '@backstage/frontend-plugin-api'; +import { FrontendModule } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -52,4 +53,15 @@ export function createSpecializedApp(options?: { }): { createRoot(): JSX_2.Element; }; + +// @public (undocumented) +export type FrontendFeature = + | FrontendPlugin + | FrontendModule + | { + $$type: '@backstage/ExtensionOverrides'; + } + | { + $$type: '@backstage/BackstagePlugin'; + }; ``` diff --git a/packages/frontend-app-api/src/routing/RouteTracker.test.tsx b/packages/frontend-app-api/src/routing/RouteTracker.test.tsx index 935449b697..aeec03992f 100644 --- a/packages/frontend-app-api/src/routing/RouteTracker.test.tsx +++ b/packages/frontend-app-api/src/routing/RouteTracker.test.tsx @@ -46,7 +46,10 @@ describe('RouteTracker', () => { caseSensitive: false, children: [MATCH_ALL_ROUTE], appNode: { - spec: { extension: { id: 'home.page.index' }, source: { id: 'home' } }, + spec: { + extension: { id: 'home.page.index' }, + source: { id: 'home' }, + }, } as AppNode, }, { diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.ts b/packages/frontend-app-api/src/routing/collectRouteIds.ts index d45871ae89..d89834c02e 100644 --- a/packages/frontend-app-api/src/routing/collectRouteIds.ts +++ b/packages/frontend-app-api/src/routing/collectRouteIds.ts @@ -18,7 +18,6 @@ import { RouteRef, SubRouteRef, ExternalRouteRef, - FrontendFeature, } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { @@ -29,6 +28,9 @@ import { import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalSubRouteRef } from '../../../frontend-plugin-api/src/routing/SubRouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { isInternalFrontendPlugin } from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin'; +import { FrontendFeature } from '../wiring'; /** @internal */ export interface RouteRefsById { @@ -42,7 +44,7 @@ export function collectRouteIds(features: FrontendFeature[]): RouteRefsById { const externalRoutesById = new Map(); for (const feature of features) { - if (feature.$$type !== '@backstage/BackstagePlugin') { + if (!isInternalFrontendPlugin(feature)) { continue; } diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index b92485c5d6..1ccc7bae7f 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -14,20 +14,19 @@ * limitations under the License. */ -import { - BackstagePlugin, - Extension, - ExtensionOverrides, - FrontendFeature, -} from '@backstage/frontend-plugin-api'; +import { Extension, ExtensionOverrides } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; import { ExtensionParameters } from './readAppExtensionsConfig'; import { AppNodeSpec } from '@backstage/frontend-plugin-api'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin'; +import { + isInternalFrontendPlugin, + toInternalFrontendPlugin, +} from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExtension } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; +import { FrontendFeature } from '../wiring'; /** @internal */ export function resolveAppNodeSpecs(options: { @@ -43,16 +42,14 @@ export function resolveAppNodeSpecs(options: { features = [], } = options; - const plugins = features.filter( - (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', - ); + const plugins = features.filter(isInternalFrontendPlugin); const overrides = features.filter( (f): f is ExtensionOverrides => f.$$type === '@backstage/ExtensionOverrides', ); const pluginExtensions = plugins.flatMap(source => { - return toInternalBackstagePlugin(source).extensions.map(extension => ({ + return toInternalFrontendPlugin(source).extensions.map(extension => ({ ...extension, source, })); diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index 908298cb9a..1a92a0eb7d 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -23,6 +23,7 @@ import { PageBlueprint, createFrontendPlugin, ThemeBlueprint, + createFrontendModule, } from '@backstage/frontend-plugin-api'; import { screen, waitFor } from '@testing-library/react'; import { CreateAppFeatureLoader, createApp } from './createApp'; @@ -379,4 +380,57 @@ describe('createApp', () => { expect(screen.queryByText('Custom app root element')).toBeNull(); }); + + describe('modules', () => { + it('should be able to override extensions with a plugin extension override', async () => { + const mod = createFrontendModule({ + pluginId: 'app', + extensions: [ + appPlugin.getExtension('app/root').override({ + factory: () => [ + coreExtensionData.reactElement( +
Custom app root element
, + ), + ], + }), + ], + }); + + const app = createApp({ + configLoader: () => new Promise(() => {}), + features: [mod], + }); + + await renderWithEffects(app.createRoot()); + + expect(screen.queryByText('Custom app root element')).toBeNull(); + }); + + it('should be able to override extensions with a standalone extension override', async () => { + const mod = createFrontendModule({ + pluginId: 'app', + extensions: [ + createExtension({ + name: 'root', + attachTo: { id: 'app', input: 'root' }, + output: [coreExtensionData.reactElement], + factory: () => [ + coreExtensionData.reactElement( +
Custom app root element
, + ), + ], + }), + ], + }); + + const app = createApp({ + configLoader: () => new Promise(() => {}), + features: [mod], + }); + + await renderWithEffects(app.createRoot()); + + expect(screen.queryByText('Custom app root element')).toBeNull(); + }); + }); }); diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 37b7d2758a..591dee9a00 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -22,7 +22,6 @@ import { AppTreeApi, appTreeApiRef, coreExtensionData, - FrontendFeature, RouteRef, ExternalRouteRef, SubRouteRef, @@ -61,7 +60,15 @@ import { RouteResolver } from '../routing/RouteResolver'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin'; +import { + toInternalFrontendPlugin, + isInternalFrontendPlugin, +} from '../../../frontend-plugin-api/src/wiring/createFrontendPlugin'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + toInternalFrontendModule, + isInternalFrontendModule, +} from '../../../frontend-plugin-api/src/wiring/createFrontendModule'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; import { stringifyError } from '@backstage/errors'; @@ -77,6 +84,7 @@ import { ApiRegistry } from '../../../core-app-api/src/apis/system/ApiRegistry'; import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; import { BackstageRouteObject } from '../routing/types'; import appPlugin from '@backstage/plugin-app'; +import { FrontendFeature } from './types'; function deduplicateFeatures( allFeatures: FrontendFeature[], @@ -89,7 +97,7 @@ function deduplicateFeatures( return features .reverse() .filter(feature => { - if (feature.$$type !== '@backstage/BackstagePlugin') { + if (!isInternalFrontendPlugin(feature)) { return true; } if (seenIds.has(feature.id)) { @@ -318,14 +326,22 @@ export function createSpecializedApp(options?: { const featureFlagApi = apiHolder.get(featureFlagsApiRef); if (featureFlagApi) { for (const feature of features) { - if (feature.$$type === '@backstage/BackstagePlugin') { - toInternalBackstagePlugin(feature).featureFlags.forEach(flag => + if (isInternalFrontendPlugin(feature)) { + toInternalFrontendPlugin(feature).featureFlags.forEach(flag => featureFlagApi.registerFlag({ name: flag.name, pluginId: feature.id, }), ); } + if (isInternalFrontendModule(feature)) { + toInternalFrontendModule(feature).featureFlags.forEach(flag => + featureFlagApi.registerFlag({ + name: flag.name, + pluginId: feature.pluginId, + }), + ); + } if (feature.$$type === '@backstage/ExtensionOverrides') { toInternalExtensionOverrides(feature).featureFlags.forEach(flag => featureFlagApi.registerFlag({ name: flag.name, pluginId: '' }), diff --git a/packages/frontend-app-api/src/wiring/discovery.ts b/packages/frontend-app-api/src/wiring/discovery.ts index 4e50290350..6f9d2e2d16 100644 --- a/packages/frontend-app-api/src/wiring/discovery.ts +++ b/packages/frontend-app-api/src/wiring/discovery.ts @@ -15,7 +15,7 @@ */ import { Config, ConfigReader } from '@backstage/config'; -import { FrontendFeature } from '@backstage/frontend-plugin-api'; +import { FrontendFeature } from '@backstage/frontend-app-api'; interface DiscoveryGlobal { modules: Array<{ name: string; export?: string; default: unknown }>; @@ -84,6 +84,10 @@ export function getAvailableFeatures(config: Config): FrontendFeature[] { function isBackstageFeature(obj: unknown): obj is FrontendFeature { if (obj !== null && typeof obj === 'object' && '$$type' in obj) { return ( + obj.$$type === '@backstage/FrontendPlugin' || + obj.$$type === '@backstage/FrontendModule' || + // TODO: Remove this once the old plugin type and extension overrides + // are no longer supported obj.$$type === '@backstage/BackstagePlugin' || obj.$$type === '@backstage/ExtensionOverrides' ); diff --git a/packages/frontend-app-api/src/wiring/index.ts b/packages/frontend-app-api/src/wiring/index.ts index d1498514c8..bcf623d740 100644 --- a/packages/frontend-app-api/src/wiring/index.ts +++ b/packages/frontend-app-api/src/wiring/index.ts @@ -19,3 +19,4 @@ export { createSpecializedApp, type CreateAppFeatureLoader, } from './createApp'; +export * from './types'; diff --git a/packages/frontend-app-api/src/wiring/types.ts b/packages/frontend-app-api/src/wiring/types.ts new file mode 100644 index 0000000000..fb887534e3 --- /dev/null +++ b/packages/frontend-app-api/src/wiring/types.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2024 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. + */ +import { FrontendModule, FrontendPlugin } from '@backstage/frontend-plugin-api'; + +/** @public */ +export type FrontendFeature = + | FrontendPlugin + | FrontendModule + // TODO(blam): This is just forwards backwards compatibility, remove after v1.31.0 + | { $$type: '@backstage/ExtensionOverrides' } + | { $$type: '@backstage/BackstagePlugin' }; diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 9c1907775b..b42efddffa 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -320,29 +320,14 @@ export { BackstageIdentityApi }; export { BackstageIdentityResponse }; -// @public (undocumented) -export interface BackstagePlugin< +// @public @deprecated (undocumented) +export type BackstagePlugin< TRoutes extends AnyRoutes = AnyRoutes, TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, TExtensionMap extends { [id in string]: ExtensionDefinition; } = {}, -> { - // (undocumented) - readonly $$type: '@backstage/BackstagePlugin'; - // (undocumented) - readonly externalRoutes: TExternalRoutes; - // (undocumented) - getExtension(id: TId): TExtensionMap[TId]; - // (undocumented) - readonly id: string; - // (undocumented) - readonly routes: TRoutes; - // (undocumented) - withOverrides(options: { - extensions: Array; - }): BackstagePlugin; -} +> = FrontendPlugin; export { BackstageUserIdentity }; @@ -732,7 +717,7 @@ export type CreateExtensionOptions< }): Iterable; } & VerifyExtensionFactoryOutput; -// @public (undocumented) +// @public @deprecated (undocumented) export function createExtensionOverrides( options: ExtensionOverridesOptions, ): ExtensionOverrides; @@ -760,6 +745,25 @@ export function createExternalRouteRef< } >; +// @public (undocumented) +export function createFrontendModule< + TId extends string, + TExtensions extends readonly ExtensionDefinition[] = [], +>(options: CreateFrontendModuleOptions): FrontendModule; + +// @public (undocumented) +export interface CreateFrontendModuleOptions< + TPluginId extends string, + TExtensions extends readonly ExtensionDefinition[], +> { + // (undocumented) + extensions?: TExtensions; + // (undocumented) + featureFlags?: FeatureFlagConfig[]; + // (undocumented) + pluginId: TPluginId; +} + // @public (undocumented) export function createFrontendPlugin< TId extends string, @@ -768,7 +772,7 @@ export function createFrontendPlugin< TExtensions extends readonly ExtensionDefinition[] = [], >( options: PluginOptions, -): BackstagePlugin< +): FrontendPlugin< TRoutes, TExternalRoutes, { @@ -1204,7 +1208,7 @@ export interface ExtensionOverrides { readonly $$type: '@backstage/ExtensionOverrides'; } -// @public (undocumented) +// @public @deprecated (undocumented) export interface ExtensionOverridesOptions { // (undocumented) extensions: ExtensionDefinition[]; @@ -1241,8 +1245,40 @@ export { FetchApi }; export { fetchApiRef }; +// @public @deprecated (undocumented) +export type FrontendFeature = FrontendPlugin | ExtensionOverrides; + // @public (undocumented) -export type FrontendFeature = BackstagePlugin | ExtensionOverrides; +export interface FrontendModule { + // (undocumented) + readonly $$type: '@backstage/FrontendModule'; + // (undocumented) + readonly pluginId: string; +} + +// @public (undocumented) +export interface FrontendPlugin< + TRoutes extends AnyRoutes = AnyRoutes, + TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, + TExtensionMap extends { + [id in string]: ExtensionDefinition; + } = {}, +> { + // (undocumented) + readonly $$type: '@backstage/FrontendPlugin'; + // (undocumented) + readonly externalRoutes: TExternalRoutes; + // (undocumented) + getExtension(id: TId): TExtensionMap[TId]; + // (undocumented) + readonly id: string; + // (undocumented) + readonly routes: TRoutes; + // (undocumented) + withOverrides(options: { + extensions: Array; + }): FrontendPlugin; +} export { githubAuthApiRef }; diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts index 5add7b79b9..887f9b8dab 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts @@ -21,7 +21,10 @@ import { } from './resolveExtensionDefinition'; import { ExtensionOverrides, FeatureFlagConfig } from './types'; -/** @public */ +/** + * @deprecated Use {@link createFrontendModule} instead. + * @public + */ export interface ExtensionOverridesOptions { extensions: ExtensionDefinition[]; featureFlags?: FeatureFlagConfig[]; @@ -34,7 +37,10 @@ export interface InternalExtensionOverrides extends ExtensionOverrides { readonly featureFlags: FeatureFlagConfig[]; } -/** @public */ +/** + * @deprecated Use {@link createFrontendModule} instead. + * @public + */ export function createExtensionOverrides( options: ExtensionOverridesOptions, ): ExtensionOverrides { diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendModule.test.ts b/packages/frontend-plugin-api/src/wiring/createFrontendModule.test.ts new file mode 100644 index 0000000000..d895f6de0f --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/createFrontendModule.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright 2024 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. + */ +import { createExtension } from './createExtension'; +import { createFrontendModule } from './createFrontendModule'; + +describe('createFrontendModule', () => { + it('should create a frontend module', () => { + expect( + createFrontendModule({ + pluginId: 'test', + extensions: [ + createExtension({ + kind: 'route', + name: 'test', + output: [], + attachTo: { id: 'ignored', input: 'ignored' }, + factory: () => [], + }), + ], + }), + ).toMatchInlineSnapshot(` + { + "$$type": "@backstage/FrontendModule", + "extensions": [ + { + "$$type": "@backstage/Extension", + "T": undefined, + "attachTo": { + "id": "ignored", + "input": "ignored", + }, + "configSchema": undefined, + "disabled": false, + "factory": [Function], + "id": "route:test/test", + "inputs": {}, + "output": [], + "toString": [Function], + "version": "v2", + }, + ], + "featureFlags": [], + "pluginId": "test", + "toString": [Function], + "version": "v1", + } + `); + }); +}); diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts b/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts new file mode 100644 index 0000000000..aacc34ccf0 --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/createFrontendModule.ts @@ -0,0 +1,127 @@ +/* + * 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. + */ + +import { + ExtensionDefinition, + InternalExtensionDefinition, + toInternalExtensionDefinition, +} from './createExtension'; +import { + Extension, + resolveExtensionDefinition, +} from './resolveExtensionDefinition'; +import { FeatureFlagConfig } from './types'; + +/** @public */ +export interface CreateFrontendModuleOptions< + TPluginId extends string, + TExtensions extends readonly ExtensionDefinition[], +> { + pluginId: TPluginId; + extensions?: TExtensions; + featureFlags?: FeatureFlagConfig[]; +} + +/** @public */ +export interface FrontendModule { + readonly $$type: '@backstage/FrontendModule'; + readonly pluginId: string; +} + +/** @internal */ +export interface InternalFrontendModule extends FrontendModule { + readonly version: 'v1'; + readonly extensions: Extension[]; + readonly featureFlags: FeatureFlagConfig[]; +} + +/** @public */ +export function createFrontendModule< + TId extends string, + TExtensions extends readonly ExtensionDefinition[] = [], +>(options: CreateFrontendModuleOptions): FrontendModule { + const { pluginId } = options; + + const extensions = new Array>(); + const extensionDefinitionsById = new Map< + string, + InternalExtensionDefinition + >(); + + for (const def of options.extensions ?? []) { + const internal = toInternalExtensionDefinition(def); + const ext = resolveExtensionDefinition(def, { namespace: pluginId }); + extensions.push(ext); + extensionDefinitionsById.set(ext.id, { + ...internal, + namespace: pluginId, + }); + } + + if (extensions.length !== extensionDefinitionsById.size) { + const extensionIds = extensions.map(e => e.id); + const duplicates = Array.from( + new Set( + extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index), + ), + ); + // TODO(Rugvip): This could provide some more information about the kind + name of the extensions + throw new Error( + `Plugin '${pluginId}' provided duplicate extensions: ${duplicates.join( + ', ', + )}`, + ); + } + + return { + $$type: '@backstage/FrontendModule', + version: 'v1', + pluginId, + featureFlags: options.featureFlags ?? [], + extensions, + toString() { + return `Module{pluginId=${pluginId}}`; + }, + } as InternalFrontendModule; +} + +/** @internal */ +export function isInternalFrontendModule(opaque: { + $$type: string; +}): opaque is InternalFrontendModule { + if (opaque.$$type === '@backstage/FrontendModule') { + // Make sure we throw if invalid + toInternalFrontendModule(opaque as FrontendModule); + return true; + } + return false; +} + +/** @internal */ +export function toInternalFrontendModule( + plugin: FrontendModule, +): InternalFrontendModule { + const internal = plugin as InternalFrontendModule; + if (internal.$$type !== '@backstage/FrontendModule') { + throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`); + } + if (internal.version !== 'v1') { + throw new Error( + `Invalid plugin instance, bad version '${internal.version}'`, + ); + } + return internal; +} diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.test.ts b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.test.ts index 83ae085856..c461d6fb20 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.test.ts @@ -17,14 +17,13 @@ import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { screen } from '@testing-library/react'; -import { createFrontendPlugin } from './createFrontendPlugin'; +import { FrontendPlugin, createFrontendPlugin } from './createFrontendPlugin'; import { JsonObject } from '@backstage/types'; import { createExtension } from './createExtension'; import { createExtensionDataRef } from './createExtensionDataRef'; import { coreExtensionData } from './coreExtensionData'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import { createExtensionInput } from './createExtensionInput'; -import { BackstagePlugin } from './types'; const nameExtensionDataRef = createExtensionDataRef().with({ id: 'name', @@ -123,7 +122,7 @@ function createTestAppRoot({ features, config = {}, }: { - features: BackstagePlugin[]; + features: FrontendPlugin[]; config: JsonObject; }) { return createApp({ diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts index 2bea1fe8be..03c843543d 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts @@ -24,13 +24,33 @@ import { ResolveExtensionId, resolveExtensionDefinition, } from './resolveExtensionDefinition'; -import { - AnyExternalRoutes, - AnyRoutes, - BackstagePlugin, - FeatureFlagConfig, -} from './types'; +import { AnyExternalRoutes, AnyRoutes, FeatureFlagConfig } from './types'; +/** @public */ +export interface FrontendPlugin< + TRoutes extends AnyRoutes = AnyRoutes, + TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, + TExtensionMap extends { [id in string]: ExtensionDefinition } = {}, +> { + readonly $$type: '@backstage/FrontendPlugin'; + readonly id: string; + readonly routes: TRoutes; + readonly externalRoutes: TExternalRoutes; + getExtension(id: TId): TExtensionMap[TId]; + withOverrides(options: { + extensions: Array; + }): FrontendPlugin; +} + +/** + * @public + * @deprecated Use {@link FrontendPlugin} instead. + */ +export type BackstagePlugin< + TRoutes extends AnyRoutes = AnyRoutes, + TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, + TExtensionMap extends { [id in string]: ExtensionDefinition } = {}, +> = FrontendPlugin; /** @public */ export interface PluginOptions< TId extends string, @@ -46,10 +66,10 @@ export interface PluginOptions< } /** @public */ -export interface InternalBackstagePlugin< +export interface InternalFrontendPlugin< TRoutes extends AnyRoutes = AnyRoutes, TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, -> extends BackstagePlugin { +> extends FrontendPlugin { readonly version: 'v1'; readonly extensions: Extension[]; readonly featureFlags: FeatureFlagConfig[]; @@ -63,7 +83,7 @@ export function createFrontendPlugin< TExtensions extends readonly ExtensionDefinition[] = [], >( options: PluginOptions, -): BackstagePlugin< +): FrontendPlugin< TRoutes, TExternalRoutes, { @@ -105,7 +125,7 @@ export function createFrontendPlugin< } return { - $$type: '@backstage/BackstagePlugin', + $$type: '@backstage/FrontendPlugin', version: 'v1', id: options.id, routes: options.routes ?? ({} as TRoutes), @@ -135,15 +155,33 @@ export function createFrontendPlugin< extensions: [...nonOverriddenExtensions, ...overrides.extensions], }); }, - } as InternalBackstagePlugin; + } as InternalFrontendPlugin; } /** @internal */ -export function toInternalBackstagePlugin( - plugin: BackstagePlugin, -): InternalBackstagePlugin { - const internal = plugin as InternalBackstagePlugin; - if (internal.$$type !== '@backstage/BackstagePlugin') { +export function isInternalFrontendPlugin(opaque: { + $$type: string; +}): opaque is InternalFrontendPlugin { + if ( + opaque.$$type === '@backstage/FrontendPlugin' || + opaque.$$type === '@backstage/BackstagePlugin' + ) { + // Make sure we throw if invalid + toInternalFrontendPlugin(opaque as FrontendPlugin); + return true; + } + return false; +} + +/** @internal */ +export function toInternalFrontendPlugin( + plugin: FrontendPlugin, +): InternalFrontendPlugin { + const internal = plugin as InternalFrontendPlugin; + if ( + internal.$$type !== '@backstage/FrontendPlugin' && + internal.$$type !== '@backstage/BackstagePlugin' + ) { throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`); } if (internal.version !== 'v1') { diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index 6e136a6514..f8ad362bac 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -39,8 +39,15 @@ export { export { createPlugin, createFrontendPlugin, + type FrontendPlugin, + type BackstagePlugin, type PluginOptions, } from './createFrontendPlugin'; +export { + createFrontendModule, + type FrontendModule, + type CreateFrontendModuleOptions, +} from './createFrontendModule'; export { createExtensionOverrides, type ExtensionOverridesOptions, @@ -49,7 +56,6 @@ export { type Extension } from './resolveExtensionDefinition'; export { type AnyRoutes, type AnyExternalRoutes, - type BackstagePlugin, type ExtensionOverrides, type FeatureFlagConfig, type FrontendFeature, diff --git a/packages/frontend-plugin-api/src/wiring/types.ts b/packages/frontend-plugin-api/src/wiring/types.ts index b713b2d926..b52bbf446c 100644 --- a/packages/frontend-plugin-api/src/wiring/types.ts +++ b/packages/frontend-plugin-api/src/wiring/types.ts @@ -16,6 +16,7 @@ import { ExternalRouteRef, RouteRef, SubRouteRef } from '../routing'; import { ExtensionDefinition } from './createExtension'; +import { FrontendPlugin } from './createFrontendPlugin'; /** * Feature flag configuration. @@ -40,26 +41,13 @@ export type ExtensionMap< get(id: TId): TExtensionMap[TId]; }; -/** @public */ -export interface BackstagePlugin< - TRoutes extends AnyRoutes = AnyRoutes, - TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, - TExtensionMap extends { [id in string]: ExtensionDefinition } = {}, -> { - readonly $$type: '@backstage/BackstagePlugin'; - readonly id: string; - readonly routes: TRoutes; - readonly externalRoutes: TExternalRoutes; - getExtension(id: TId): TExtensionMap[TId]; - withOverrides(options: { - extensions: Array; - }): BackstagePlugin; -} - /** @public */ export interface ExtensionOverrides { readonly $$type: '@backstage/ExtensionOverrides'; } -/** @public */ -export type FrontendFeature = BackstagePlugin | ExtensionOverrides; +/** + * @public + * @deprecated import from {@link @backstage/frontend-app-api#FrontendFeature} instead + */ +export type FrontendFeature = FrontendPlugin | ExtensionOverrides; diff --git a/packages/frontend-test-utils/api-report.md b/packages/frontend-test-utils/api-report.md index ba4b8aae2b..10b84b0981 100644 --- a/packages/frontend-test-utils/api-report.md +++ b/packages/frontend-test-utils/api-report.md @@ -14,7 +14,7 @@ import { ErrorWithContext } from '@backstage/test-utils'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionDefinitionParameters } from '@backstage/frontend-plugin-api'; -import { FrontendFeature } from '@backstage/frontend-plugin-api'; +import { FrontendFeature } from '@backstage/frontend-app-api'; import { JsonObject } from '@backstage/types'; import { MockConfigApi } from '@backstage/test-utils'; import { MockErrorApi } from '@backstage/test-utils'; diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index 7923050050..fae67a260c 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -16,7 +16,10 @@ import React from 'react'; import { Link, MemoryRouter } from 'react-router-dom'; -import { createSpecializedApp } from '@backstage/frontend-app-api'; +import { + createSpecializedApp, + FrontendFeature, +} from '@backstage/frontend-app-api'; import { RenderResult, render } from '@testing-library/react'; import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; @@ -30,7 +33,6 @@ import { IconComponent, RouterBlueprint, NavItemBlueprint, - FrontendFeature, } from '@backstage/frontend-plugin-api'; import appPlugin from '@backstage/plugin-app'; diff --git a/plugins/api-docs/api-report-alpha.md b/plugins/api-docs/api-report-alpha.md index 70bf57ebc0..bb2da7bc0b 100644 --- a/plugins/api-docs/api-report-alpha.md +++ b/plugins/api-docs/api-report-alpha.md @@ -6,18 +6,18 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @public (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { root: RouteRef; }, diff --git a/plugins/app-visualizer/api-report.md b/plugins/app-visualizer/api-report.md index 7bf5e3608b..e542674845 100644 --- a/plugins/app-visualizer/api-report.md +++ b/plugins/app-visualizer/api-report.md @@ -4,15 +4,15 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @public (undocumented) -const visualizerPlugin: BackstagePlugin< +const visualizerPlugin: FrontendPlugin< {}, {}, { diff --git a/plugins/app/api-report.md b/plugins/app/api-report.md index 73f5076ef3..ca76ecb91b 100644 --- a/plugins/app/api-report.md +++ b/plugins/app/api-report.md @@ -9,12 +9,12 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { AppTheme } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ComponentRef } from '@backstage/frontend-plugin-api'; import { ComponentType } from 'react'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { IconComponent as IconComponent_2 } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; @@ -25,7 +25,7 @@ import { TranslationMessages } from '@backstage/frontend-plugin-api'; import { TranslationResource } from '@backstage/frontend-plugin-api'; // @public (undocumented) -const appPlugin: BackstagePlugin< +const appPlugin: FrontendPlugin< {}, {}, { diff --git a/plugins/catalog-graph/api-report-alpha.md b/plugins/catalog-graph/api-report-alpha.md index 6e1027dea0..65f8af3764 100644 --- a/plugins/catalog-graph/api-report-alpha.md +++ b/plugins/catalog-graph/api-report-alpha.md @@ -5,18 +5,18 @@ ```ts import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Direction } from '@backstage/plugin-catalog-graph'; import { Entity } from '@backstage/catalog-model'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @public (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { catalogGraph: RouteRef; }, diff --git a/plugins/catalog-import/api-report-alpha.md b/plugins/catalog-import/api-report-alpha.md index 992de9fc54..3eed9ce3e4 100644 --- a/plugins/catalog-import/api-report-alpha.md +++ b/plugins/catalog-import/api-report-alpha.md @@ -5,14 +5,14 @@ ```ts import { AnyApiFactory } from '@backstage/core-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { importPage: RouteRef; }, diff --git a/plugins/catalog/api-report-alpha.md b/plugins/catalog/api-report-alpha.md index 151794858a..62e631dd4a 100644 --- a/plugins/catalog/api-report-alpha.md +++ b/plugins/catalog/api-report-alpha.md @@ -8,13 +8,13 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { ExtensionBlueprint } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -123,7 +123,7 @@ export const catalogTranslationRef: TranslationRef< >; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { catalogIndex: RouteRef; catalogEntity: RouteRef<{ diff --git a/plugins/devtools/api-report-alpha.md b/plugins/devtools/api-report-alpha.md index a6a121ebd7..7fb16734f1 100644 --- a/plugins/devtools/api-report-alpha.md +++ b/plugins/devtools/api-report-alpha.md @@ -5,15 +5,15 @@ ```ts import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { root: RouteRef; }, diff --git a/plugins/home/api-report-alpha.md b/plugins/home/api-report-alpha.md index 7347d98d7b..7b4b157eb2 100644 --- a/plugins/home/api-report-alpha.md +++ b/plugins/home/api-report-alpha.md @@ -4,15 +4,15 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< {}, {}, { diff --git a/plugins/kubernetes/api-report-alpha.md b/plugins/kubernetes/api-report-alpha.md index b0cad703d6..852a5c6c1a 100644 --- a/plugins/kubernetes/api-report-alpha.md +++ b/plugins/kubernetes/api-report-alpha.md @@ -7,15 +7,15 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @public (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { kubernetes: RouteRef; }, diff --git a/plugins/org/api-report-alpha.md b/plugins/org/api-report-alpha.md index c50e28bc7d..a8c6bd70ec 100644 --- a/plugins/org/api-report-alpha.md +++ b/plugins/org/api-report-alpha.md @@ -3,15 +3,15 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< {}, { catalogIndex: ExternalRouteRef; diff --git a/plugins/scaffolder/api-report-alpha.md b/plugins/scaffolder/api-report-alpha.md index 7758cc59d2..555ab2ac13 100644 --- a/plugins/scaffolder/api-report-alpha.md +++ b/plugins/scaffolder/api-report-alpha.md @@ -5,13 +5,13 @@ ```ts import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import type { FormProps as FormProps_2 } from '@rjsf/core'; import { FormProps as FormProps_3 } from '@backstage/plugin-scaffolder-react'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; import { PathParams } from '@backstage/core-plugin-api'; @@ -24,7 +24,7 @@ import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { root: RouteRef; selectedTemplate: SubRouteRef< diff --git a/plugins/search/api-report-alpha.md b/plugins/search/api-report-alpha.md index 9e043ab792..fe06873bd4 100644 --- a/plugins/search/api-report-alpha.md +++ b/plugins/search/api-report-alpha.md @@ -5,10 +5,10 @@ ```ts import { AnyApiFactory } from '@backstage/core-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -16,7 +16,7 @@ import { SearchResultItemExtensionComponent } from '@backstage/plugin-search-rea import { SearchResultItemExtensionPredicate } from '@backstage/plugin-search-react/alpha'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { root: RouteRef; }, diff --git a/plugins/techdocs/api-report-alpha.md b/plugins/techdocs/api-report-alpha.md index 881778d5ae..6a22a9fce9 100644 --- a/plugins/techdocs/api-report-alpha.md +++ b/plugins/techdocs/api-report-alpha.md @@ -6,11 +6,11 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api'; import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -18,7 +18,7 @@ import { SearchResultItemExtensionComponent } from '@backstage/plugin-search-rea import { SearchResultItemExtensionPredicate } from '@backstage/plugin-search-react/alpha'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { root: RouteRef; docRoot: RouteRef<{ diff --git a/plugins/user-settings/api-report-alpha.md b/plugins/user-settings/api-report-alpha.md index c8e320e7d0..199dbba582 100644 --- a/plugins/user-settings/api-report-alpha.md +++ b/plugins/user-settings/api-report-alpha.md @@ -4,17 +4,17 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; +import { FrontendPlugin } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) -const _default: BackstagePlugin< +const _default: FrontendPlugin< { root: RouteRef; },