From d194acb0e3bee584de220306e1419c8b765f2050 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 16 Jan 2026 16:56:47 +0100 Subject: [PATCH] frontend-plugin-api: move new PluginWrapper to alpha Signed-off-by: Patrik Oldsberg --- .changeset/violet-otters-share.md | 2 +- packages/frontend-plugin-api/package.json | 4 ++ .../frontend-plugin-api/report-alpha.api.md | 68 +++++++++++++++++++ packages/frontend-plugin-api/report.api.md | 53 --------------- packages/frontend-plugin-api/src/alpha.ts | 27 ++++++++ .../src/apis/definitions/PluginWrapperApi.ts | 10 +-- .../src/apis/definitions/index.ts | 1 - .../blueprints/AppRootWrapperBlueprint.tsx | 9 +-- .../src/blueprints/PluginWrapperBlueprint.tsx | 2 +- .../src/blueprints/index.ts | 1 - .../DefaultPluginWrapperApi.tsx | 2 +- .../app/src/extensions/PluginWrapperApi.ts | 4 +- 12 files changed, 115 insertions(+), 68 deletions(-) create mode 100644 packages/frontend-plugin-api/report-alpha.api.md create mode 100644 packages/frontend-plugin-api/src/alpha.ts diff --git a/.changeset/violet-otters-share.md b/.changeset/violet-otters-share.md index daed39f98c..e60ba5041d 100644 --- a/.changeset/violet-otters-share.md +++ b/.changeset/violet-otters-share.md @@ -2,4 +2,4 @@ '@backstage/frontend-plugin-api': patch --- -Added `PluginWrapperBlueprint`, which can install components that will wrap all plugin elements. The `AppRootWrapperBlueprint` has also been deprecated and should be replaced either with the new plugin wrapper, or for app overrides, the new blueprint with the same name from `@backstage/plugin-app-react`. +Added an alpha `PluginWrapperBlueprint` exported from `@backstage/frontend-plugin-api/alpha`, which can install components that will wrap all plugin elements. The `AppRootWrapperBlueprint` has also been deprecated and should be replaced either with the new plugin wrapper, or for app overrides, the new blueprint with the same name from `@backstage/plugin-app-react`. diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 358977bad4..5c82ef444d 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -16,12 +16,16 @@ "sideEffects": false, "exports": { ".": "./src/index.ts", + "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, "main": "src/index.ts", "types": "src/index.ts", "typesVersions": { "*": { + "alpha": [ + "src/alpha.ts" + ], "package.json": [ "package.json" ] diff --git a/packages/frontend-plugin-api/report-alpha.api.md b/packages/frontend-plugin-api/report-alpha.api.md new file mode 100644 index 0000000000..77a377bb8e --- /dev/null +++ b/packages/frontend-plugin-api/report-alpha.api.md @@ -0,0 +1,68 @@ +## API Report File for "@backstage/frontend-plugin-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ApiRef } from '@backstage/frontend-plugin-api'; +import { ComponentType } from 'react'; +import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { ExtensionBlueprint } from '@backstage/frontend-plugin-api'; +import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; +import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { ReactNode } from 'react'; + +// @alpha +export type PluginWrapperApi = { + getPluginWrapper(pluginId: string): + | ComponentType<{ + children: ReactNode; + }> + | undefined; +}; + +// @alpha +export const pluginWrapperApiRef: ApiRef; + +// @alpha +export const PluginWrapperBlueprint: ExtensionBlueprint<{ + kind: 'plugin-wrapper'; + params: (params: { + loader: () => Promise<{ + component: ComponentType<{ + children: ReactNode; + }>; + }>; + }) => ExtensionBlueprintParams<{ + loader: () => Promise<{ + component: ComponentType<{ + children: ReactNode; + }>; + }>; + }>; + output: ExtensionDataRef< + () => Promise<{ + component: ComponentType<{ + children: ReactNode; + }>; + }>, + 'core.plugin-wrapper.loader', + {} + >; + inputs: {}; + config: {}; + configInput: {}; + dataRefs: { + wrapper: ConfigurableExtensionDataRef< + () => Promise<{ + component: ComponentType<{ + children: ReactNode; + }>; + }>, + 'core.plugin-wrapper.loader', + {} + >; + }; +}>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index fe19b724ce..1a7f2e3c7a 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -1868,59 +1868,6 @@ export interface PluginOptions< routes?: TRoutes; } -// @public -export type PluginWrapperApi = { - getPluginWrapper(pluginId: string): - | ComponentType<{ - children: ReactNode; - }> - | undefined; -}; - -// @public -export const pluginWrapperApiRef: ApiRef; - -// @public -export const PluginWrapperBlueprint: ExtensionBlueprint_2<{ - kind: 'plugin-wrapper'; - params: (params: { - loader: () => Promise<{ - component: ComponentType<{ - children: ReactNode; - }>; - }>; - }) => ExtensionBlueprintParams_2<{ - loader: () => Promise<{ - component: ComponentType<{ - children: ReactNode; - }>; - }>; - }>; - output: ExtensionDataRef_2< - () => Promise<{ - component: ComponentType<{ - children: ReactNode; - }>; - }>, - 'core.plugin-wrapper.loader', - {} - >; - inputs: {}; - config: {}; - configInput: {}; - dataRefs: { - wrapper: ConfigurableExtensionDataRef_2< - () => Promise<{ - component: ComponentType<{ - children: ReactNode; - }>; - }>, - 'core.plugin-wrapper.loader', - {} - >; - }; -}>; - // @public (undocumented) export type PortableSchema = { parse: (input: TInput) => TOutput; diff --git a/packages/frontend-plugin-api/src/alpha.ts b/packages/frontend-plugin-api/src/alpha.ts new file mode 100644 index 0000000000..9d73b8cc84 --- /dev/null +++ b/packages/frontend-plugin-api/src/alpha.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +/** + * Alpha exports for plugin wrapper functionality. + * + * @alpha + */ + +export { PluginWrapperBlueprint } from './blueprints/PluginWrapperBlueprint'; +export { + type PluginWrapperApi, + pluginWrapperApiRef, +} from './apis/definitions/PluginWrapperApi'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts b/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts index 6a1f921282..a4b66d6128 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/PluginWrapperApi.ts @@ -15,7 +15,7 @@ */ import { ComponentType, ReactNode } from 'react'; -import { ApiRef, createApiRef } from '../system'; +import { createApiRef } from '@backstage/frontend-plugin-api'; /** * The Plugin Wrapper API is used to wrap plugin extensions with providers, @@ -27,7 +27,7 @@ import { ApiRef, createApiRef } from '../system'; * system, but can be used for advanced use-cases. If you do override it, be * sure to include the default implementation as well. * - * @public + * @alpha */ export type PluginWrapperApi = { /** @@ -43,8 +43,8 @@ export type PluginWrapperApi = { /** * The API reference of {@link PluginWrapperApi}. * - * @public + * @alpha */ -export const pluginWrapperApiRef: ApiRef = createApiRef({ - id: 'core.plugin-wrapper', +export const pluginWrapperApiRef = createApiRef({ + id: 'core.plugin-wrapper.alpha', }); diff --git a/packages/frontend-plugin-api/src/apis/definitions/index.ts b/packages/frontend-plugin-api/src/apis/definitions/index.ts index 7b90d38092..5e7f713fcf 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/index.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/index.ts @@ -49,4 +49,3 @@ export * from './RouteResolutionApi'; export * from './StorageApi'; export * from './AnalyticsApi'; export * from './TranslationApi'; -export * from './PluginWrapperApi'; diff --git a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx index 62268bce77..0fbefa7d08 100644 --- a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.tsx @@ -27,10 +27,11 @@ const componentDataRef = createExtensionDataRef< * and similar. * * @public - * @deprecated Use {@link PluginWrapperBlueprint} instead if you want to wrap - * all plugin components in the same wrapper. If you want to wrap the entire - * app, use the `AppRootWrapperBlueprint` from `@backstage/plugin-app-react` - * instead, although note that only app modules are able to use that blueprint. + * @deprecated Use `PluginWrapperBlueprint` from + * `@backstage/frontend-plugin-api/alpha` instead if you want to wrap all plugin + * components in the same wrapper. If you want to wrap the entire app, use the + * `AppRootWrapperBlueprint` from `@backstage/plugin-app-react` instead, + * although note that only app modules are able to use that blueprint. */ export const AppRootWrapperBlueprint = createExtensionBlueprint({ kind: 'app-root-wrapper', diff --git a/packages/frontend-plugin-api/src/blueprints/PluginWrapperBlueprint.tsx b/packages/frontend-plugin-api/src/blueprints/PluginWrapperBlueprint.tsx index a005342b31..4bec4a4390 100644 --- a/packages/frontend-plugin-api/src/blueprints/PluginWrapperBlueprint.tsx +++ b/packages/frontend-plugin-api/src/blueprints/PluginWrapperBlueprint.tsx @@ -28,7 +28,7 @@ const wrapperDataRef = createExtensionDataRef< /** * Creates extensions that wrap plugin extensions with providers. * - * @public + * @alpha */ export const PluginWrapperBlueprint = createExtensionBlueprint({ kind: 'plugin-wrapper', diff --git a/packages/frontend-plugin-api/src/blueprints/index.ts b/packages/frontend-plugin-api/src/blueprints/index.ts index 1d7e6eb478..379c8d237b 100644 --- a/packages/frontend-plugin-api/src/blueprints/index.ts +++ b/packages/frontend-plugin-api/src/blueprints/index.ts @@ -21,7 +21,6 @@ export { export { ApiBlueprint } from './ApiBlueprint'; export { AppRootElementBlueprint } from './AppRootElementBlueprint'; export { AppRootWrapperBlueprint } from './AppRootWrapperBlueprint'; -export { PluginWrapperBlueprint } from './PluginWrapperBlueprint'; export { IconBundleBlueprint } from './IconBundleBlueprint'; export { NavContentBlueprint, diff --git a/plugins/app/src/apis/PluginWrapperApi/DefaultPluginWrapperApi.tsx b/plugins/app/src/apis/PluginWrapperApi/DefaultPluginWrapperApi.tsx index 2bf2744f21..65c41ee2e2 100644 --- a/plugins/app/src/apis/PluginWrapperApi/DefaultPluginWrapperApi.tsx +++ b/plugins/app/src/apis/PluginWrapperApi/DefaultPluginWrapperApi.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { PluginWrapperApi } from '@backstage/frontend-plugin-api'; +import { PluginWrapperApi } from '@backstage/frontend-plugin-api/alpha'; import { ComponentType, ReactNode, useEffect, useState } from 'react'; type WrapperInput = { diff --git a/plugins/app/src/extensions/PluginWrapperApi.ts b/plugins/app/src/extensions/PluginWrapperApi.ts index 14e41891a0..e402f094f1 100644 --- a/plugins/app/src/extensions/PluginWrapperApi.ts +++ b/plugins/app/src/extensions/PluginWrapperApi.ts @@ -16,9 +16,11 @@ import { PluginWrapperBlueprint, + pluginWrapperApiRef, +} from '@backstage/frontend-plugin-api/alpha'; +import { createExtensionInput, ApiBlueprint, - pluginWrapperApiRef, } from '@backstage/frontend-plugin-api'; import { DefaultPluginWrapperApi } from '../apis/PluginWrapperApi';