Merge pull request #26245 from backstage/blam/namespace-be-gone
NFS: Introduce `createFrontendModule` as a replacement for `createExtensionOverrides`
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': patch
|
||||
'@backstage/core-compat-api': patch
|
||||
---
|
||||
|
||||
Added support for new `FrontendPlugin` and `FrontendModule` types.
|
||||
@@ -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<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ?? {}),
|
||||
|
||||
@@ -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<NewBackstagePlugin, LegacyBackstagePlugin>(),
|
||||
() => new WeakMap<NewFrontendPlugin, LegacyBackstagePlugin>(),
|
||||
);
|
||||
|
||||
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(),
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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';
|
||||
};
|
||||
```
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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<string, ExternalRouteRef>();
|
||||
|
||||
for (const feature of features) {
|
||||
if (feature.$$type !== '@backstage/BackstagePlugin') {
|
||||
if (!isInternalFrontendPlugin(feature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}));
|
||||
|
||||
@@ -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(
|
||||
<div>Custom app root element</div>,
|
||||
),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
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(
|
||||
<div>Custom app root element</div>,
|
||||
),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const app = createApp({
|
||||
configLoader: () => new Promise(() => {}),
|
||||
features: [mod],
|
||||
});
|
||||
|
||||
await renderWithEffects(app.createRoot());
|
||||
|
||||
expect(screen.queryByText('Custom app root element')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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: '' }),
|
||||
|
||||
@@ -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'
|
||||
);
|
||||
|
||||
@@ -19,3 +19,4 @@ export {
|
||||
createSpecializedApp,
|
||||
type CreateAppFeatureLoader,
|
||||
} from './createApp';
|
||||
export * from './types';
|
||||
|
||||
@@ -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' };
|
||||
@@ -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<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
||||
// (undocumented)
|
||||
readonly id: string;
|
||||
// (undocumented)
|
||||
readonly routes: TRoutes;
|
||||
// (undocumented)
|
||||
withOverrides(options: {
|
||||
extensions: Array<ExtensionDefinition>;
|
||||
}): BackstagePlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
}
|
||||
> = FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
|
||||
export { BackstageUserIdentity };
|
||||
|
||||
@@ -732,7 +717,7 @@ export type CreateExtensionOptions<
|
||||
}): Iterable<UFactoryOutput>;
|
||||
} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;
|
||||
|
||||
// @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<TId, TExtensions>): 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<TId, TRoutes, TExternalRoutes, TExtensions>,
|
||||
): 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<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
||||
// (undocumented)
|
||||
readonly id: string;
|
||||
// (undocumented)
|
||||
readonly routes: TRoutes;
|
||||
// (undocumented)
|
||||
withOverrides(options: {
|
||||
extensions: Array<ExtensionDefinition>;
|
||||
}): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
}
|
||||
|
||||
export { githubAuthApiRef };
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
@@ -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<unknown>[];
|
||||
readonly featureFlags: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function createFrontendModule<
|
||||
TId extends string,
|
||||
TExtensions extends readonly ExtensionDefinition[] = [],
|
||||
>(options: CreateFrontendModuleOptions<TId, TExtensions>): FrontendModule {
|
||||
const { pluginId } = options;
|
||||
|
||||
const extensions = new Array<Extension<any>>();
|
||||
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;
|
||||
}
|
||||
@@ -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<string>().with({
|
||||
id: 'name',
|
||||
@@ -123,7 +122,7 @@ function createTestAppRoot({
|
||||
features,
|
||||
config = {},
|
||||
}: {
|
||||
features: BackstagePlugin[];
|
||||
features: FrontendPlugin[];
|
||||
config: JsonObject;
|
||||
}) {
|
||||
return createApp({
|
||||
|
||||
@@ -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<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
||||
withOverrides(options: {
|
||||
extensions: Array<ExtensionDefinition>;
|
||||
}): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Use {@link FrontendPlugin} instead.
|
||||
*/
|
||||
export type BackstagePlugin<
|
||||
TRoutes extends AnyRoutes = AnyRoutes,
|
||||
TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
TExtensionMap extends { [id in string]: ExtensionDefinition } = {},
|
||||
> = FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
/** @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<TRoutes, TExternalRoutes> {
|
||||
> extends FrontendPlugin<TRoutes, TExternalRoutes> {
|
||||
readonly version: 'v1';
|
||||
readonly extensions: Extension<unknown>[];
|
||||
readonly featureFlags: FeatureFlagConfig[];
|
||||
@@ -63,7 +83,7 @@ export function createFrontendPlugin<
|
||||
TExtensions extends readonly ExtensionDefinition[] = [],
|
||||
>(
|
||||
options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
|
||||
): 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<TRoutes, TExternalRoutes>;
|
||||
} as InternalFrontendPlugin<TRoutes, TExternalRoutes>;
|
||||
}
|
||||
|
||||
/** @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') {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<TId extends keyof TExtensionMap>(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<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
||||
withOverrides(options: {
|
||||
extensions: Array<ExtensionDefinition>;
|
||||
}): BackstagePlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
||||
}
|
||||
|
||||
/** @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;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
@@ -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<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
|
||||
@@ -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<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
@@ -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<undefined>;
|
||||
catalogEntity: RouteRef<{
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
@@ -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<
|
||||
{},
|
||||
{},
|
||||
{
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
@@ -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<undefined>;
|
||||
|
||||
@@ -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<undefined>;
|
||||
selectedTemplate: SubRouteRef<
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
@@ -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<undefined>;
|
||||
docRoot: RouteRef<{
|
||||
|
||||
@@ -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<undefined>;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user