frontend-plugin-api, frontend-app-api: API review cleanup

Remove @backstage/core-plugin-api leakage from the
@backstage/frontend-app-api public API surface. Rename PluginOptions
to CreateFrontendPluginOptions with a deprecated alias. Remove
ResolvedExtensionInputs from the main @backstage/frontend-plugin-api
entry point.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-17 11:37:13 +01:00
parent bf41231deb
commit 5fd78ba82f
12 changed files with 95 additions and 60 deletions
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': patch
---
Removed `@backstage/core-plugin-api` leakage from the public API surface. All types such as `ApiHolder` and `ConfigApi` are now imported from `@backstage/frontend-plugin-api`.
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': minor
---
Renamed `PluginOptions` to `CreateFrontendPluginOptions` and deprecated the old name. Removed `ResolvedExtensionInputs` from the main entry point; it is still available as an inline type in extension factory signatures.
+3 -4
View File
@@ -3,11 +3,10 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { ApiHolder } from '@backstage/core-plugin-api';
import { ApiHolder as ApiHolder_2 } from '@backstage/frontend-plugin-api';
import { ApiHolder } from '@backstage/frontend-plugin-api';
import { AppNode } from '@backstage/frontend-plugin-api';
import { AppTree } from '@backstage/frontend-plugin-api';
import { ConfigApi } from '@backstage/core-plugin-api';
import { ConfigApi } from '@backstage/frontend-plugin-api';
import { ExtensionDataContainer } from '@backstage/frontend-plugin-api';
import { ExtensionDataRef } from '@backstage/frontend-plugin-api';
import { ExtensionDataValue } from '@backstage/frontend-plugin-api';
@@ -186,7 +185,7 @@ export type ExtensionFactoryMiddleware = (
}) => ExtensionDataContainer<ExtensionDataRef>,
context: {
node: AppNode;
apis: ApiHolder_2;
apis: ApiHolder;
config?: JsonObject;
},
) => Iterable<ExtensionDataValue<any, any>>;
@@ -19,8 +19,9 @@ import {
ExtensionDataContainer,
ExtensionDataRef,
ExtensionInput,
ResolvedExtensionInputs,
} from '@backstage/frontend-plugin-api';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { ResolvedExtensionInputs } from '../../../frontend-plugin-api/src/wiring/createExtension';
import { ExtensionFactoryMiddleware } from '../wiring/types';
import mapValues from 'lodash/mapValues';
import { AppNode, AppNodeInstance } from '@backstage/frontend-plugin-api';
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { ConfigApi } from '@backstage/core-plugin-api';
import { ConfigApi } from '@backstage/frontend-plugin-api';
import {
FrontendFeature,
FrontendPluginInfo,
@@ -28,12 +28,13 @@ import {
createExtensionInput,
useRouteRef,
analyticsApiRef,
configApiRef,
createExtensionDataRef,
featureFlagsApiRef,
} from '@backstage/frontend-plugin-api';
import { screen, render } from '@testing-library/react';
import { createSpecializedApp } from './createSpecializedApp';
import { mockApis, TestApiRegistry } from '@backstage/test-utils';
import { configApiRef, featureFlagsApiRef } from '@backstage/core-plugin-api';
import { MemoryRouter } from 'react-router-dom';
import { ApiProvider, ConfigReader } from '@backstage/core-app-api';
import { Fragment } from 'react';
@@ -16,30 +16,28 @@
import { ConfigReader } from '@backstage/config';
import {
AnyApiFactory,
ApiBlueprint,
ApiHolder,
AppNode,
AppTree,
AppTreeApi,
appTreeApiRef,
RouteRef,
ExternalRouteRef,
SubRouteRef,
AnyRouteRefParams,
RouteFunc,
RouteResolutionApi,
createApiFactory,
routeResolutionApiRef,
AppNode,
FrontendFeature,
} from '@backstage/frontend-plugin-api';
import { ExtensionFactoryMiddleware } from './types';
import {
AnyApiFactory,
ApiHolder,
ConfigApi,
configApiRef,
createApiFactory,
ExternalRouteRef,
featureFlagsApiRef,
FrontendFeature,
identityApiRef,
} from '@backstage/core-plugin-api';
RouteFunc,
RouteRef,
RouteResolutionApi,
routeResolutionApiRef,
SubRouteRef,
} from '@backstage/frontend-plugin-api';
import { ExtensionFactoryMiddleware } from './types';
import { ApiFactoryRegistry, ApiResolver } from '@backstage/core-app-api';
import {
createExtensionDataContainer,
@@ -24,8 +24,9 @@ import {
ExtensionDefinitionParameters,
ExtensionInput,
PortableSchema,
ResolvedExtensionInputs,
} from '@backstage/frontend-plugin-api';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { ResolvedExtensionInputs } from '../../../frontend-plugin-api/src/wiring/createExtension';
import { OpaqueType } from '@internal/opaque';
export const OpaqueExtensionDefinition = OpaqueType.create<{
+36 -32
View File
@@ -729,13 +729,45 @@ export function createFrontendPlugin<
[name in string]: ExternalRouteRef;
} = {},
>(
options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
options: CreateFrontendPluginOptions<
TId,
TRoutes,
TExternalRoutes,
TExtensions
>,
): OverridableFrontendPlugin<
TRoutes,
TExternalRoutes,
MakeSortedExtensionsMap<TExtensions[number], TId>
>;
// @public
export interface CreateFrontendPluginOptions<
TId extends string,
TRoutes extends {
[name in string]: RouteRef | SubRouteRef;
},
TExternalRoutes extends {
[name in string]: ExternalRouteRef;
},
TExtensions extends readonly ExtensionDefinition[],
> {
// (undocumented)
extensions?: TExtensions;
// (undocumented)
externalRoutes?: TExternalRoutes;
// (undocumented)
featureFlags?: FeatureFlagConfig[];
icon?: IconElement;
// (undocumented)
info?: FrontendPluginInfoOptions;
// (undocumented)
pluginId: TId;
// (undocumented)
routes?: TRoutes;
title?: string;
}
// @public
export function createRouteRef<
TParams extends
@@ -1847,8 +1879,8 @@ export type PluginHeaderActionsApi = {
// @public
export const pluginHeaderActionsApiRef: ApiRef_2<PluginHeaderActionsApi>;
// @public (undocumented)
export interface PluginOptions<
// @public @deprecated (undocumented)
export type PluginOptions<
TId extends string,
TRoutes extends {
[name in string]: RouteRef | SubRouteRef;
@@ -1857,22 +1889,7 @@ export interface PluginOptions<
[name in string]: ExternalRouteRef;
},
TExtensions extends readonly ExtensionDefinition[],
> {
// (undocumented)
extensions?: TExtensions;
// (undocumented)
externalRoutes?: TExternalRoutes;
// (undocumented)
featureFlags?: FeatureFlagConfig[];
icon?: IconElement;
// (undocumented)
info?: FrontendPluginInfoOptions;
// (undocumented)
pluginId: TId;
// (undocumented)
routes?: TRoutes;
title?: string;
}
> = CreateFrontendPluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>;
// @public
export type PluginWrapperApi = {
@@ -1950,19 +1967,6 @@ export const Progress: {
// @public (undocumented)
export type ProgressProps = {};
// @public
export type ResolvedExtensionInputs<
TInputs extends {
[name in string]: ExtensionInput;
},
> = {
[InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton']
? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>>
: false extends TInputs[InputName]['config']['optional']
? Expand<ResolvedExtensionInput<TInputs[InputName]>>
: Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;
};
// @public
export type RouteFunc<TParams extends AnyRouteRefParams> = (
...input: TParams extends undefined ? readonly [] : readonly [params: TParams]
@@ -53,7 +53,8 @@ type ResolvedExtensionInput<TExtensionInput extends ExtensionInput> =
/**
* Converts an extension input map into a matching collection of resolved inputs.
* @public
*
* @ignore
*/
export type ResolvedExtensionInputs<
TInputs extends {
@@ -170,8 +170,12 @@ export interface FrontendPlugin<
info(): Promise<FrontendPluginInfo>;
}
/** @public */
export interface PluginOptions<
/**
* Options for {@link createFrontendPlugin}.
*
* @public
*/
export interface CreateFrontendPluginOptions<
TId extends string,
TRoutes extends { [name in string]: RouteRef | SubRouteRef },
TExternalRoutes extends { [name in string]: ExternalRouteRef },
@@ -194,6 +198,17 @@ export interface PluginOptions<
info?: FrontendPluginInfoOptions;
}
/**
* @deprecated Use {@link CreateFrontendPluginOptions} instead.
* @public
*/
export type PluginOptions<
TId extends string,
TRoutes extends { [name in string]: RouteRef | SubRouteRef },
TExternalRoutes extends { [name in string]: ExternalRouteRef },
TExtensions extends readonly ExtensionDefinition[],
> = CreateFrontendPluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>;
/**
* Creates a new plugin that can be installed in a Backstage app.
*
@@ -230,7 +245,12 @@ export function createFrontendPlugin<
TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {},
TExternalRoutes extends { [name in string]: ExternalRouteRef } = {},
>(
options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
options: CreateFrontendPluginOptions<
TId,
TRoutes,
TExternalRoutes,
TExtensions
>,
): OverridableFrontendPlugin<
TRoutes,
TExternalRoutes,
@@ -22,7 +22,6 @@ export {
type ExtensionDefinitionParameters,
type CreateExtensionOptions,
type OverridableExtensionDefinition,
type ResolvedExtensionInputs,
} from './createExtension';
export {
createExtensionInput,
@@ -36,6 +35,7 @@ export {
} from './createExtensionDataRef';
export {
createFrontendPlugin,
type CreateFrontendPluginOptions,
type FrontendPlugin,
type OverridableFrontendPlugin,
type PluginOptions,