core-plugin-api: remove exprerimental plugin options

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-09-24 18:30:11 +02:00
parent 959aa2a09f
commit 322bbcae24
16 changed files with 24 additions and 270 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': patch
---
Internal update for removal of experimental plugin configuration API.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/test-utils': patch
---
Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-plugin-api': minor
---
Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed.
@@ -4,9 +4,7 @@
```ts
import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { Observable } from '@backstage/types';
import { ReactNode } from 'react';
import { TranslationMessages as TranslationMessages_2 } from '@backstage/core-plugin-api/alpha';
import { TranslationRef as TranslationRef_2 } from '@backstage/core-plugin-api/alpha';
@@ -74,17 +72,6 @@ export function createTranslationResource<
options: TranslationResourceOptions<TId, TMessages, TTranslations>,
): TranslationResource<TId>;
// @alpha
export interface PluginOptionsProviderProps {
// (undocumented)
children: ReactNode;
// (undocumented)
plugin?: BackstagePlugin;
}
// @alpha
export const PluginProvider: (props: PluginOptionsProviderProps) => JSX.Element;
// @alpha (undocumented)
export type TranslationApi = {
getTranslation<
@@ -245,11 +232,6 @@ export type TranslationSnapshot<
t: TranslationFunction<TMessages>;
};
// @alpha
export function usePluginOptions<
TPluginOptions extends {} = {},
>(): TPluginOptions;
// @alpha (undocumented)
export const useTranslationRef: <
TMessages extends {
+3 -7
View File
@@ -222,7 +222,7 @@ export type BackstageIdentityResponse = {
export type BackstagePlugin<
Routes extends AnyRoutes = {},
ExternalRoutes extends AnyExternalRoutes = {},
PluginInputOptions extends {} = {},
_Ignored extends {} = {},
> = {
getId(): string;
getApis(): Iterable<AnyApiFactory>;
@@ -230,7 +230,6 @@ export type BackstagePlugin<
provide<T>(extension: Extension<T>): T;
routes: Routes;
externalRoutes: ExternalRoutes;
__experimentalReconfigure(options: PluginInputOptions): void;
};
// @public
@@ -318,10 +317,9 @@ export function createExternalRouteRef<
export function createPlugin<
Routes extends AnyRoutes = {},
ExternalRoutes extends AnyExternalRoutes = {},
PluginInputOptions extends {} = {},
>(
config: PluginConfig<Routes, ExternalRoutes, PluginInputOptions>,
): BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions>;
config: PluginConfig<Routes, ExternalRoutes>,
): BackstagePlugin<Routes, ExternalRoutes>;
// @public
export function createReactExtension<
@@ -647,14 +645,12 @@ export type PendingOAuthRequest = {
export type PluginConfig<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes,
PluginInputOptions extends {},
> = {
id: string;
apis?: Iterable<AnyApiFactory>;
routes?: Routes;
externalRoutes?: ExternalRoutes;
featureFlags?: PluginFeatureFlagConfig[];
__experimentalConfigure?(options?: PluginInputOptions): {};
};
// @public
-1
View File
@@ -14,6 +14,5 @@
* limitations under the License.
*/
export * from './plugin-options';
export * from './translation';
export * from './apis/alpha';
@@ -21,7 +21,6 @@ import { RouteRef, useRouteRef } from '../routing';
import { attachComponentData } from './componentData';
import { Extension, BackstagePlugin } from '../plugin';
import { PluginErrorBoundary } from './PluginErrorBoundary';
import { PluginProvider } from '../plugin-options';
import { routableExtensionRenderedEvent } from '../analytics/Tracker';
/**
@@ -258,9 +257,7 @@ export function createReactExtension<
...(mountPoint && { routeRef: mountPoint.id }),
}}
>
<PluginProvider plugin={plugin}>
<Component {...props} />
</PluginProvider>
<Component {...props} />
</AnalyticsContext>
</PluginErrorBoundary>
</Suspense>
@@ -1,18 +0,0 @@
/*
* Copyright 2020 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.
*/
export { usePluginOptions, PluginProvider } from './usePluginOptions';
export type { PluginOptionsProviderProps } from './usePluginOptions';
@@ -1,53 +0,0 @@
/*
* Copyright 2021 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 React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { usePluginOptions, PluginProvider } from './usePluginOptions';
import { createPlugin } from '../plugin';
describe('usePluginOptions', () => {
it('should provide a versioned value to hook', () => {
type TestInputPluginOptions = {
'key-1': string;
};
type TestPluginOptions = {
'key-1': string;
'key-2': string;
};
const plugin = createPlugin({
id: 'my-plugin',
__experimentalConfigure(_: TestInputPluginOptions): TestPluginOptions {
return { 'key-1': 'value-1', 'key-2': 'value-2' };
},
});
const rendered = renderHook(() => usePluginOptions(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
<PluginProvider plugin={plugin}>{children}</PluginProvider>
),
});
const config = rendered.result.current;
expect(config).toEqual({
'key-1': 'value-1',
'key-2': 'value-2',
});
});
});
@@ -1,93 +0,0 @@
/*
* Copyright 2020 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 {
createVersionedContext,
createVersionedValueMap,
useVersionedContext,
} from '@backstage/version-bridge';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import React, { ReactNode } from 'react';
const contextKey: string = 'plugin-context';
/**
* Properties for the PluginProvider component.
*
* @alpha
*/
export interface PluginOptionsProviderProps {
children: ReactNode;
plugin?: BackstagePlugin;
}
/**
* Contains the plugin configuration.
*
* @alpha
*/
export const PluginProvider = (
props: PluginOptionsProviderProps,
): JSX.Element => {
const { children, plugin } = props;
const { Provider } = createVersionedContext<{
1: { plugin: BackstagePlugin | undefined };
}>(contextKey);
return (
<Provider
value={createVersionedValueMap({
1: {
plugin,
},
})}
>
{children}
</Provider>
);
};
/**
* Grab the current entity from the context, throws if the entity has not yet been loaded
* or is not available.
*
* @alpha
*/
export function usePluginOptions<
TPluginOptions extends {} = {},
>(): TPluginOptions {
const versionedHolder = useVersionedContext<{ 1: TPluginOptions }>(
contextKey,
);
if (!versionedHolder) {
throw new Error('Plugin Options context is not available');
}
const value = versionedHolder.atVersion(1);
if (!value) {
throw new Error('Plugin Options v1 is not available');
}
return (
value as unknown as {
plugin: {
getPluginOptions(): {};
};
}
).plugin.getPluginOptions() as TPluginOptions;
}
+4 -27
View File
@@ -30,18 +30,9 @@ import { AnyApiFactory } from '../apis';
export class PluginImpl<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes,
PluginInputOptions extends {},
> implements BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions>
> implements BackstagePlugin<Routes, ExternalRoutes>
{
constructor(
private readonly config: PluginConfig<
Routes,
ExternalRoutes,
PluginInputOptions
>,
) {}
private options: {} | undefined = undefined;
constructor(private readonly config: PluginConfig<Routes, ExternalRoutes>) {}
getId(): string {
return this.config.id;
@@ -67,19 +58,6 @@ export class PluginImpl<
return extension.expose(this);
}
__experimentalReconfigure(options: PluginInputOptions): void {
if (this.config.__experimentalConfigure) {
this.options = this.config.__experimentalConfigure(options);
}
}
getPluginOptions(): {} {
if (this.config.__experimentalConfigure && !this.options) {
this.options = this.config.__experimentalConfigure();
}
return this.options ?? {};
}
toString() {
return `plugin{${this.config.id}}`;
}
@@ -94,9 +72,8 @@ export class PluginImpl<
export function createPlugin<
Routes extends AnyRoutes = {},
ExternalRoutes extends AnyExternalRoutes = {},
PluginInputOptions extends {} = {},
>(
config: PluginConfig<Routes, ExternalRoutes, PluginInputOptions>,
): BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions> {
config: PluginConfig<Routes, ExternalRoutes>,
): BackstagePlugin<Routes, ExternalRoutes> {
return new PluginImpl(config);
}
+1 -4
View File
@@ -52,7 +52,7 @@ export type AnyExternalRoutes = { [name: string]: ExternalRouteRef };
export type BackstagePlugin<
Routes extends AnyRoutes = {},
ExternalRoutes extends AnyExternalRoutes = {},
PluginInputOptions extends {} = {},
_Ignored extends {} = {},
> = {
getId(): string;
getApis(): Iterable<AnyApiFactory>;
@@ -63,7 +63,6 @@ export type BackstagePlugin<
provide<T>(extension: Extension<T>): T;
routes: Routes;
externalRoutes: ExternalRoutes;
__experimentalReconfigure(options: PluginInputOptions): void;
};
/**
@@ -84,14 +83,12 @@ export type PluginFeatureFlagConfig = {
export type PluginConfig<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes,
PluginInputOptions extends {},
> = {
id: string;
apis?: Iterable<AnyApiFactory>;
routes?: Routes;
externalRoutes?: ExternalRoutes;
featureFlags?: PluginFeatureFlagConfig[];
__experimentalConfigure?(options?: PluginInputOptions): {};
};
/**
@@ -314,7 +314,6 @@ function toLegacyPlugin(plugin: BackstagePlugin): LegacyBackstagePlugin {
getApis: notImplemented,
getFeatureFlags: notImplemented,
provide: notImplemented,
__experimentalReconfigure: notImplemented,
};
}
-7
View File
@@ -4,17 +4,10 @@
```ts
import { Observable } from '@backstage/types';
import { PropsWithChildren } from 'react';
import { default as React_2 } from 'react';
import { TranslationApi } from '@backstage/core-plugin-api/alpha';
import { TranslationRef } from '@backstage/core-plugin-api/alpha';
import { TranslationSnapshot } from '@backstage/core-plugin-api/alpha';
// @alpha
export const MockPluginProvider: ({
children,
}: PropsWithChildren<{}>) => React_2.JSX.Element;
// @alpha (undocumented)
export class MockTranslationApi implements TranslationApi {
// (undocumented)
-1
View File
@@ -14,5 +14,4 @@
* limitations under the License.
*/
export * from './testUtils/MockPluginProvider';
export * from './testUtils/apis/TranslationApi';
@@ -1,36 +0,0 @@
/*
* Copyright 2020 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 React, { PropsWithChildren } from 'react';
import { PluginProvider } from '@backstage/core-plugin-api/alpha';
import { createPlugin } from '@backstage/core-plugin-api';
/**
* Mock for PluginProvider to use in unit tests
* @alpha
*/
export const MockPluginProvider = ({ children }: PropsWithChildren<{}>) => {
type TestInputPluginOptions = {};
type TestPluginOptions = {};
const plugin = createPlugin({
id: 'my-plugin',
__experimentalConfigure(_: TestInputPluginOptions): TestPluginOptions {
return {};
},
});
return <PluginProvider plugin={plugin}>{children}</PluginProvider>;
};