introduce FrontendFeature
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-plugin-api': patch
|
||||
---
|
||||
|
||||
Add the `FrontendFeature` type, which is the union of `BackstagePlugin` and `ExtensionOverrides`
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': patch
|
||||
'@backstage/core-compat-api': patch
|
||||
---
|
||||
|
||||
Leverage the new `FrontendFeature` type to simplify interfaces
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
```ts
|
||||
import { AnyRouteRefParams } from '@backstage/core-plugin-api';
|
||||
import { BackstagePlugin } 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 { default as React_2 } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
@@ -21,7 +20,7 @@ export function compatWrapper(element: ReactNode): React_2.JSX.Element;
|
||||
// @public (undocumented)
|
||||
export function convertLegacyApp(
|
||||
rootElement: React_2.JSX.Element,
|
||||
): (ExtensionOverrides | BackstagePlugin)[];
|
||||
): FrontendFeature[];
|
||||
|
||||
// @public
|
||||
export function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(
|
||||
|
||||
@@ -22,8 +22,7 @@ import React, {
|
||||
isValidElement,
|
||||
} from 'react';
|
||||
import {
|
||||
BackstagePlugin,
|
||||
ExtensionOverrides,
|
||||
FrontendFeature,
|
||||
coreExtensionData,
|
||||
createExtension,
|
||||
createExtensionInput,
|
||||
@@ -61,7 +60,7 @@ function selectChildren(
|
||||
/** @public */
|
||||
export function convertLegacyApp(
|
||||
rootElement: React.JSX.Element,
|
||||
): (ExtensionOverrides | BackstagePlugin)[] {
|
||||
): FrontendFeature[] {
|
||||
if (getComponentData(rootElement, 'core.type') === 'FlatRoutes') {
|
||||
return collectLegacyRoutes(rootElement);
|
||||
}
|
||||
|
||||
@@ -3,26 +3,23 @@
|
||||
> 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 { Config } from '@backstage/config';
|
||||
import { ConfigApi } from '@backstage/core-plugin-api';
|
||||
import { ExtensionDataRef } from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionOverrides } from '@backstage/frontend-plugin-api';
|
||||
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { FrontendFeature } from '@backstage/frontend-plugin-api';
|
||||
import { JSX as JSX_2 } from 'react';
|
||||
import { RouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { SubRouteRef } from '@backstage/frontend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export function createApp(options?: {
|
||||
features?: (BackstagePlugin | ExtensionOverrides)[];
|
||||
features?: FrontendFeature[];
|
||||
configLoader?: () => Promise<{
|
||||
config: ConfigApi;
|
||||
}>;
|
||||
bindRoutes?(context: { bind: CreateAppRouteBinder }): void;
|
||||
featureLoader?: (ctx: {
|
||||
config: ConfigApi;
|
||||
}) => Promise<(BackstagePlugin | ExtensionOverrides)[]>;
|
||||
featureLoader?: (ctx: { config: ConfigApi }) => Promise<FrontendFeature[]>;
|
||||
}): {
|
||||
createRoot(): JSX_2.Element;
|
||||
};
|
||||
@@ -45,7 +42,7 @@ export function createExtensionTree(options: { config: Config }): ExtensionTree;
|
||||
|
||||
// @public
|
||||
export function createSpecializedApp(options?: {
|
||||
features?: (BackstagePlugin | ExtensionOverrides)[];
|
||||
features?: FrontendFeature[];
|
||||
config?: ConfigApi;
|
||||
bindRoutes?(context: { bind: CreateAppRouteBinder }): void;
|
||||
}): {
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
BackstagePlugin,
|
||||
ExtensionOverrides,
|
||||
RouteRef,
|
||||
SubRouteRef,
|
||||
ExternalRouteRef,
|
||||
FrontendFeature,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef';
|
||||
@@ -33,9 +32,7 @@ export interface RouteRefsById {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function collectRouteIds(
|
||||
features: (BackstagePlugin | ExtensionOverrides)[],
|
||||
): RouteRefsById {
|
||||
export function collectRouteIds(features: FrontendFeature[]): RouteRefsById {
|
||||
const routesById = new Map<string, RouteRef | SubRouteRef>();
|
||||
const externalRoutesById = new Map<string, ExternalRouteRef>();
|
||||
|
||||
|
||||
@@ -14,11 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
BackstagePlugin,
|
||||
Extension,
|
||||
ExtensionOverrides,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { Extension, FrontendFeature } from '@backstage/frontend-plugin-api';
|
||||
import { readAppExtensionsConfig } from './readAppExtensionsConfig';
|
||||
import { resolveAppTree } from './resolveAppTree';
|
||||
import { resolveAppNodeSpecs } from './resolveAppNodeSpecs';
|
||||
@@ -28,7 +24,7 @@ import { instantiateAppNodeTree } from './instantiateAppNodeTree';
|
||||
|
||||
/** @internal */
|
||||
export interface CreateAppTreeOptions {
|
||||
features: (BackstagePlugin | ExtensionOverrides)[];
|
||||
features: FrontendFeature[];
|
||||
builtinExtensions: Extension<unknown>[];
|
||||
config: Config;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
BackstagePlugin,
|
||||
Extension,
|
||||
ExtensionOverrides,
|
||||
FrontendFeature,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides';
|
||||
@@ -30,7 +31,7 @@ import { toInternalExtension } from '../../../frontend-plugin-api/src/wiring/res
|
||||
|
||||
/** @internal */
|
||||
export function resolveAppNodeSpecs(options: {
|
||||
features: (BackstagePlugin | ExtensionOverrides)[];
|
||||
features: FrontendFeature[];
|
||||
builtinExtensions: Extension<unknown>[];
|
||||
parameters: Array<ExtensionParameters>;
|
||||
forbidden?: Set<string>;
|
||||
|
||||
@@ -19,7 +19,6 @@ import { ConfigReader, Config } from '@backstage/config';
|
||||
import {
|
||||
AppTree,
|
||||
appTreeApiRef,
|
||||
BackstagePlugin,
|
||||
ComponentRef,
|
||||
componentsApiRef,
|
||||
coreExtensionData,
|
||||
@@ -29,7 +28,7 @@ import {
|
||||
createThemeExtension,
|
||||
createTranslationExtension,
|
||||
ExtensionDataRef,
|
||||
ExtensionOverrides,
|
||||
FrontendFeature,
|
||||
RouteRef,
|
||||
useRouteRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
@@ -217,8 +216,8 @@ export function createExtensionTree(options: {
|
||||
}
|
||||
|
||||
function deduplicateFeatures(
|
||||
allFeatures: (BackstagePlugin | ExtensionOverrides)[],
|
||||
): (BackstagePlugin | ExtensionOverrides)[] {
|
||||
allFeatures: FrontendFeature[],
|
||||
): FrontendFeature[] {
|
||||
// Start by removing duplicates by reference
|
||||
const features = Array.from(new Set(allFeatures));
|
||||
|
||||
@@ -241,12 +240,10 @@ function deduplicateFeatures(
|
||||
|
||||
/** @public */
|
||||
export function createApp(options?: {
|
||||
features?: (BackstagePlugin | ExtensionOverrides)[];
|
||||
features?: FrontendFeature[];
|
||||
configLoader?: () => Promise<{ config: ConfigApi }>;
|
||||
bindRoutes?(context: { bind: CreateAppRouteBinder }): void;
|
||||
featureLoader?: (ctx: {
|
||||
config: ConfigApi;
|
||||
}) => Promise<(BackstagePlugin | ExtensionOverrides)[]>;
|
||||
featureLoader?: (ctx: { config: ConfigApi }) => Promise<FrontendFeature[]>;
|
||||
}): {
|
||||
createRoot(): JSX.Element;
|
||||
} {
|
||||
@@ -291,7 +288,7 @@ export function createApp(options?: {
|
||||
* @public
|
||||
*/
|
||||
export function createSpecializedApp(options?: {
|
||||
features?: (BackstagePlugin | ExtensionOverrides)[];
|
||||
features?: FrontendFeature[];
|
||||
config?: ConfigApi;
|
||||
bindRoutes?(context: { bind: CreateAppRouteBinder }): void;
|
||||
}): { createRoot(): JSX.Element } {
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
BackstagePlugin,
|
||||
ExtensionOverrides,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { FrontendFeature } from '@backstage/frontend-plugin-api';
|
||||
|
||||
interface DiscoveryGlobal {
|
||||
modules: Array<{ name: string; export?: string; default: unknown }>;
|
||||
@@ -58,9 +55,7 @@ function readPackageDetectionConfig(config: Config) {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function getAvailableFeatures(
|
||||
config: Config,
|
||||
): (BackstagePlugin | ExtensionOverrides)[] {
|
||||
export function getAvailableFeatures(config: Config): FrontendFeature[] {
|
||||
const discovered = (
|
||||
window as { '__@backstage/discovered__'?: DiscoveryGlobal }
|
||||
)['__@backstage/discovered__'];
|
||||
@@ -86,9 +81,7 @@ export function getAvailableFeatures(
|
||||
);
|
||||
}
|
||||
|
||||
function isBackstageFeature(
|
||||
obj: unknown,
|
||||
): obj is BackstagePlugin | ExtensionOverrides {
|
||||
function isBackstageFeature(obj: unknown): obj is FrontendFeature {
|
||||
if (obj !== null && typeof obj === 'object' && '$$type' in obj) {
|
||||
return (
|
||||
obj.$$type === '@backstage/BackstagePlugin' ||
|
||||
|
||||
@@ -863,6 +863,9 @@ export { FetchApi };
|
||||
|
||||
export { fetchApiRef };
|
||||
|
||||
// @public (undocumented)
|
||||
export type FrontendFeature = BackstagePlugin | ExtensionOverrides;
|
||||
|
||||
export { githubAuthApiRef };
|
||||
|
||||
export { gitlabAuthApiRef };
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
Extension,
|
||||
resolveExtensionDefinition,
|
||||
} from './resolveExtensionDefinition';
|
||||
import { FeatureFlagConfig } from './types';
|
||||
import { ExtensionOverrides, FeatureFlagConfig } from './types';
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionOverridesOptions {
|
||||
@@ -27,11 +27,6 @@ export interface ExtensionOverridesOptions {
|
||||
featureFlags?: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionOverrides {
|
||||
readonly $$type: '@backstage/ExtensionOverrides';
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface InternalExtensionOverrides extends ExtensionOverrides {
|
||||
readonly version: 'v1';
|
||||
|
||||
@@ -18,13 +18,14 @@ import React from 'react';
|
||||
import { createApp } from '@backstage/frontend-app-api';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { createSchemaFromZod } from '../schema/createSchemaFromZod';
|
||||
import { createPlugin, BackstagePlugin } from './createPlugin';
|
||||
import { createPlugin } from './createPlugin';
|
||||
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>('name');
|
||||
|
||||
|
||||
@@ -15,18 +15,16 @@
|
||||
*/
|
||||
|
||||
import { ExtensionDefinition } from './createExtension';
|
||||
import { ExternalRouteRef, RouteRef } from '../routing';
|
||||
import { FeatureFlagConfig } from './types';
|
||||
import {
|
||||
Extension,
|
||||
resolveExtensionDefinition,
|
||||
} from './resolveExtensionDefinition';
|
||||
|
||||
/** @public */
|
||||
export type AnyRoutes = { [name in string]: RouteRef };
|
||||
|
||||
/** @public */
|
||||
export type AnyExternalRoutes = { [name in string]: ExternalRouteRef };
|
||||
import {
|
||||
AnyExternalRoutes,
|
||||
AnyRoutes,
|
||||
BackstagePlugin,
|
||||
FeatureFlagConfig,
|
||||
} from './types';
|
||||
|
||||
/** @public */
|
||||
export interface PluginOptions<
|
||||
@@ -40,17 +38,6 @@ export interface PluginOptions<
|
||||
featureFlags?: FeatureFlagConfig[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackstagePlugin<
|
||||
Routes extends AnyRoutes = AnyRoutes,
|
||||
ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
> {
|
||||
readonly $$type: '@backstage/BackstagePlugin';
|
||||
readonly id: string;
|
||||
readonly routes: Routes;
|
||||
readonly externalRoutes: ExternalRoutes;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface InternalBackstagePlugin<
|
||||
Routes extends AnyRoutes = AnyRoutes,
|
||||
|
||||
@@ -34,17 +34,17 @@ export {
|
||||
type ExtensionDataRef,
|
||||
type ConfigurableExtensionDataRef,
|
||||
} from './createExtensionDataRef';
|
||||
export {
|
||||
createPlugin,
|
||||
type BackstagePlugin,
|
||||
type PluginOptions,
|
||||
type AnyRoutes,
|
||||
type AnyExternalRoutes,
|
||||
} from './createPlugin';
|
||||
export { createPlugin, type PluginOptions } from './createPlugin';
|
||||
export {
|
||||
createExtensionOverrides,
|
||||
type ExtensionOverrides,
|
||||
type ExtensionOverridesOptions,
|
||||
} from './createExtensionOverrides';
|
||||
export { type Extension } from './resolveExtensionDefinition';
|
||||
export type { FeatureFlagConfig } from './types';
|
||||
export {
|
||||
type AnyRoutes,
|
||||
type AnyExternalRoutes,
|
||||
type BackstagePlugin,
|
||||
type ExtensionOverrides,
|
||||
type FeatureFlagConfig,
|
||||
type FrontendFeature,
|
||||
} from './types';
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ExternalRouteRef, RouteRef } from '../routing';
|
||||
|
||||
/**
|
||||
* Feature flag configuration.
|
||||
*
|
||||
@@ -23,3 +25,28 @@ export type FeatureFlagConfig = {
|
||||
/** Feature flag name */
|
||||
name: string;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type AnyRoutes = { [name in string]: RouteRef };
|
||||
|
||||
/** @public */
|
||||
export type AnyExternalRoutes = { [name in string]: ExternalRouteRef };
|
||||
|
||||
/** @public */
|
||||
export interface BackstagePlugin<
|
||||
Routes extends AnyRoutes = AnyRoutes,
|
||||
ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,
|
||||
> {
|
||||
readonly $$type: '@backstage/BackstagePlugin';
|
||||
readonly id: string;
|
||||
readonly routes: Routes;
|
||||
readonly externalRoutes: ExternalRoutes;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface ExtensionOverrides {
|
||||
readonly $$type: '@backstage/ExtensionOverrides';
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type FrontendFeature = BackstagePlugin | ExtensionOverrides;
|
||||
|
||||
Reference in New Issue
Block a user